Troubleshooting: HITL or checkpoint stuck
Invocation pauses at HITL Review but no review appears#
The flow's HITL Review compiled to a @checkpoint with hitl_target: {scope, queue, hitl_spec}. ScaiCore's runtime should detect the field, auto-publish to ScaiQueue, and the message should appear in the review UI.
Check, in this order:
1. Is the checkpoint actually in pending state?#
1 2 | |
If a row exists with status: "pending" and checkpoint_type: "hitl_review", the runtime hit the checkpoint correctly. The publish step is next.
2. Did the runtime auto-publish to ScaiQueue?#
List recent messages in the configured scope:
1 2 | |
If a hitl_request message appeared with correlation_id matching the checkpoint id, the publish worked. The reviewer just hasn't seen it yet — direct them to the ScaiQueue review UI.
If no message: ScaiCore's auto-publish didn't fire. Check that the deployed Core's runtime version supports hitl_target (≥ v1.2.0). Re-deploy with a fresh wheel install of the compiler+runtime.
3. hitl_target.scope is null#
If the IR has hitl_target.scope = null, the runtime can't route the publish. Caused by an HITL Review node with no scope config AND no flow-level flow.config.scaiqueue.scope to inherit from.
Fix: Either set scope directly on the HITL Review node, OR declare a flow-level ScaiQueue topology in Flow → ScaiQueue and let the node inherit.
Reviewer clicked "approve" but the invocation is still paused#
Two possible causes:
Decision didn't reach ScaiCore#
The reviewer's response is published as a scaiqueue.message.completed event. ScaiCore subscribes and resolves the checkpoint when it arrives.
Check GET /v1/scaicore/events?core_id=$CORE_ID for a scaiqueue.message.completed event. If absent, the ScaiQueue completion didn't propagate — check ScaiQueue + ScaiCore connectivity.
Resolution string doesn't match what the flow expects#
The decision section's option ids (e.g. approve, reject) are what the runtime injects as the checkpoint's resolution. If the flow's downstream branch checks decision == "Approve" (capitalized), it won't match.
Fix: Ensure decision option ids match the conditions that consume them. Conventionally lowercase, no spaces.
Manual resolve via API#
If a checkpoint is stuck and you want to force it:
1 2 3 4 | |
Requires scaicore:manage. Useful for unblocking stuck invocations during ops triage.
Debug breakpoint won't resume#
Pending breakpoints bar in the canvas's Live Runs panel shows the paused invocation. Click "Continue" → calls POST /v1/scaicore/checkpoints/{id}/resolve with {"resolution": "continue"}.
If the click does nothing:
- Check console for a 401/403 — your token might have expired (refresh).
- Check the checkpoint actually has
checkpoint_type: "debug_breakpoint"(HITL checkpoints need a full decision body, not just "continue"). - The breakpoint flag on the node config should be unset for the next invocation, otherwise the flow pauses again. Toggle the node's breakpoint off + redeploy.
My HITL form fields aren't being filled with my flow variables#
Template expressions in section fields use {{variable}} syntax. For example:
{ "type": "input", "field": "amount", "kind": "currency", "default": "{{amount}}" }
The runtime resolves {{amount}} against the flow's current scope at the moment the checkpoint is hit. If the variable isn't bound yet (e.g. nothing upstream produced an amount), the default is empty.
Fix: Make sure an upstream block bound amount to its result (e.g. an llm_flexible node with result_binding: "amount", or a data_variable_set node). The Live Runs panel shows bound values on each block's exited event.