Skip to content

Debugging

The AI Context module includes optional debug logging to help troubleshoot consumer routing, context selection, rendering, and scope matching issues.

Enabling debug logging

  1. Navigate to /admin/config/ai/context/settings/general
  2. Expand the Debugging section
  3. Check the Enable debug logging checkbox
  4. Save the configuration

Viewing debug logs

Debug information is written to the standard Drupal log:

  1. Go to Reports > Recent log messages (/admin/reports/dblog)
  2. Filter by type: ai_context

Or using Drush:

ddev exec drush watchdog:show --type=ai_context

What gets logged

Consumer routing (AiContextPreGenerateResponseSubscriber)

When a generic chat request matches at least one consumer type, one debug line is written with the invocation status, consumer ID (if any), selected item IDs, and request tags. Agent and assistant requests are excluded. Unrouted tags write nothing.

Statuses match AiContextInvocationResult: pushed, no_items, push_disabled, type_disabled, stale, declined, ambiguous.

AiContextPreGenerateResponseSubscriber: Consumer routing; status=STATUS; consumer=ID; items=[IDS]; tags=[TAGS].

declined with an ai_automator tag and no ai_automator:id:{id} tag means the automator instance could not be identified. A temporary subscriber adds that ID when the field has exactly one automator, or when the clicked widget action UUID maps to one automator on a shared field. Multi-value fields post {uuid}_{delta} for values after 0; those names still map. That click also skips the other automators on the field when the clicked automator is allowed to push. Missing field tags, or a shared field with no matching widget click, still decline until AI core emits the ID. push_disabled means the consumer matched but automatic push is off (the Automator default until you save an override).

Usage rows are written only for pushed. Use this log, not the Usage tab, to see why a click produced no context.

The summary does not include task text or rendered context.

Context selection (AiContextSelector)

  • Scope index prefilter counts: candidate IDs vs. published IDs for Minimal without subscriptions; for Minimal with active subscriptions, per-route candidate counts (subscription, global, entity-item, exact-match) instead, since that path queries the index directly and never loads the full published-ID catalog
  • Number of published items loaded across chunks and always-include count
  • Item count after priority-group merge
  • One final selection summary with the consumer ID, selected item IDs, truncated item IDs, and token usage
  • Warning when items are truncated due to token limits
  • Warning when TEXT_RENDERED text exceeds configured max_tokens
  • Relevant prefilter counts (base, situational, and subscription candidate IDs vs. published IDs)
  • Warning when a selection scans more than 50 published items without a prefilter (once per consumer per request)

That last warning is expected for Broad, which always walks the full published catalog to fill leftover budget. Minimal and Relevant prefilter via the scope index and only fall back to a full scan when prefiltering is not possible — a scope plugin that cannot expand its subscribed values or enumerate its situational matches from indexed values. It is not a failure. It logs once per consumer per request, even if debug logging is off.

If the warning keeps appearing for a consumer on a large catalog, Minimal is the recommended mode: it skips the situational-match pass entirely, so it expands the fewest candidate IDs and loads the fewest entities. See Context selection for the trade-off.

The final debug summary uses this format:

AiContextSelector: Selection summary; consumer=CONSUMER; selected=[IDS]; truncated=[IDS]; tokens=USED/MAX.

It is emitted once per completed selection only when debug logging is enabled. The summary does not include task text, context content, provider responses, or IDs rejected by access checks.

See Selector pipeline events for when those overrides are allowed.

Scope scoring and hard context filtering run inside the selector via AiContextScopeResolver but do not emit separate debug messages.

Context rendering (AiContextRenderer)

  • Items skipped when the token budget is exhausted before or during rendering

Subcontext resolution (AiContextSubcontextResolver)

Conditional selection fails closed: when a decision cannot be completed, conditional children are excluded while required children remain selected. The resolver writes one privacy-safe warning with the parent Context Item ID, affected child count, and one of these reason categories:

  • missing_provider: no provider/model is configured, or the configured provider plugin is unavailable
  • decision_cap_exhausted: the per-request conditional parent limit was reached
  • invalid_response: the provider response is not a JSON list of scalar child IDs. Conditional subcontext asks the model for a fenced JSON code block wrapping a JSON array of child IDs (or an empty array if none), with no text before or after the fence. A bare array such as ["123"] does not decode on AI core 1.5.x, so those replies are logged with this reason and every conditional child is dropped. A fenced non-array such as "none" is also this reason, not provider_exception.
  • unsupported_provider: the provider does not support chat
  • provider_exception: provider creation or execution failed

The warning uses this format:

AiContextSubcontextResolver: Conditional children excluded; parent=PARENT; affected=COUNT; reason=REASON.

Warnings never contain Context Item content, task text, provider-response content, or exception messages. Use the parent ID to inspect configuration, then verify the provider/model, conditional parent limit, and provider logs.

Tool consumer_id inheritance (AiContextAgentToolSubscriber)

When a context tool opts in with AiContextInheritsConsumerIdInterface and a non-empty non-canonical consumer_id is replaced with agent:{running agent}, one debug line is written with the discarded value and the replacement. Omitted, empty, and canonical values do not log. This line is always written at debug. It is not gated by Enable debug logging. It does not include task text or item content.

Performance considerations

Debug logging generates significant log entries and may impact performance. Only enable it when actively troubleshooting issues. Remember to disable it when you are done debugging.