fix(16): resolve 3 UAT issues — update flow, batch cancel, text commands

- Fix update sub-workflow: remove unsupported GraphQL filter arg, fix node
  reference (Format Pull Error → Format Update Error), fix field case
  (data.image → data.Image)
- Fix batch cancel: connect Route Callback output 20 (batchcancel) to
  Prepare Batch UI Input (was empty connection array)
- Fix text commands: change .item.json to .first().json for paired item
  breakage after GraphQL chain expansion; convert Send Batch Confirmation
  from Telegram node to HTTP Request to fix double-serialized reply_markup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lucas Berger
2026-02-09 12:28:21 -05:00
parent d4fcad827a
commit 07aeace1fd
6 changed files with 292 additions and 42 deletions
+67
View File
@@ -0,0 +1,67 @@
---
status: verifying
trigger: "The cancel button on the batch confirmation dialog does not work"
created: 2026-02-09T00:00:00Z
updated: 2026-02-09T00:02:00Z
---
## Current Focus
hypothesis: CONFIRMED - Route Callback output index 20 (batchcancel) had empty connection array
test: fix applied and pushed to n8n (HTTP 200)
expecting: batch cancel button now routes to Prepare Batch UI Input -> Batch UI sub-workflow -> Handle Cancel
next_action: user verification - press cancel button on batch confirmation dialog in Telegram
## Symptoms
expected: Cancel button on batch confirmation dialog should cancel the operation and return user to previous state
actual: Cancel button does nothing (callback is parsed but routed to empty connection)
errors: No error in n8n - execution silently ends because route goes nowhere
reproduction: select containers in batch, confirm selection, press cancel on confirmation dialog
started: after Phase 16 migration (Docker socket proxy -> Unraid GraphQL API)
## Eliminated
## Evidence
- timestamp: 2026-02-09T00:00:30Z
checked: Parse Callback Data node in n8n-workflow.json (line 558)
found: batch:cancel callback is correctly parsed, sets isBatchCancel=true
implication: callback parsing is working correctly
- timestamp: 2026-02-09T00:00:40Z
checked: Route Callback switch node outputs (lines 569-1094)
found: isBatchCancel is output index 20 (outputKey "batchcancel"), the LAST output
implication: routing rule exists and should match correctly
- timestamp: 2026-02-09T00:00:50Z
checked: Route Callback connection array (lines 5495-5638)
found: Output index 20 is empty array [] (line 5637) while outputs 14-19 all connect to "Prepare Batch UI Input"
implication: ROOT CAUSE - batch:cancel callback is parsed and routed but the output goes nowhere
- timestamp: 2026-02-09T00:00:55Z
checked: Prepare Batch UI Input node (line 3420)
found: Node explicitly handles isBatchCancel -> sets action='cancel', and Batch UI sub-workflow has cancel route
implication: The downstream handling exists and is correct - only the connection is missing
- timestamp: 2026-02-09T00:01:00Z
checked: Batch UI sub-workflow cancel route (n8n-batch-ui.json line 564-576)
found: Handle Cancel node returns {action:'cancel', chatId, messageId, queryId, answerText:'Batch selection cancelled'}
implication: Sub-workflow cancel handling is complete - just needs to be reached
- timestamp: 2026-02-09T00:01:00Z
checked: batch:cancel callback sources
found: Used in 3 places: (1) batch selection UI cancel button, (2) batch stop confirmation cancel button, (3) text-command batch confirmation cancel button
implication: This broken connection affects ALL batch cancel scenarios, not just one dialog
- timestamp: 2026-02-09T00:02:00Z
checked: Fix applied - connected output 20 to "Prepare Batch UI Input"
found: JSON validated, workflow pushed to n8n successfully (HTTP 200)
implication: Fix is deployed - needs user verification via Telegram
## Resolution
root_cause: Route Callback switch node output index 20 (batchcancel) had empty connection array [] instead of connecting to "Prepare Batch UI Input" like all other batch-related outputs (indices 14-19). This was likely a wiring oversight during Phase 16 migration when batch operations were added to the Route Callback switch - the batchcancel rule was added last but its connection was left empty.
fix: Connected Route Callback output index 20 (batchcancel) to "Prepare Batch UI Input" node, matching the pattern of outputs 14-19 (bexecTextCmd, batchmode, batchtoggle, batchnav, batchexec, batchclear)
verification: Fix applied and pushed to n8n (HTTP 200). JSON validated. Awaiting user Telegram verification.
files_changed: [n8n-workflow.json]
+88
View File
@@ -0,0 +1,88 @@
---
status: verifying
trigger: "Text commands for start/stop don't work, and the batch text command confirmation dialog has no actionable buttons."
created: 2026-02-09T00:00:00Z
updated: 2026-02-09T19:00:00Z
---
## Current Focus
hypothesis: TWO root causes confirmed - (1) paired item breakage from GraphQL chain + sub-workflow calls, (2) Telegram node double-serializing reply_markup
test: Push fixed workflow to n8n and test text commands
expecting: Text start/stop commands execute successfully; batch confirmation shows clickable buttons
next_action: User verification of text commands and batch confirmation buttons
## Symptoms
expected: Text-based start/stop commands (e.g., "start plex") trigger container actions; batch text commands show confirmation with actionable buttons
actual: Text-based start/stop commands don't work at all; batch text command confirmation dialog has no actionable buttons
errors: "Paired item data for item from node 'Prepare Action Match Input' is unavailable" in Prepare Text Action Input node
reproduction: Send "start plex" or "stop sonarr" as text command; send "update all" for batch
started: After Phase 16-06 migration (Execute Command nodes replaced with GraphQL query chains)
## Eliminated
- hypothesis: Broken connections between GraphQL chain nodes and downstream nodes
evidence: All connections verified correct in workflow JSON. The chains (Query -> Normalize -> Registry -> Prepare Match Input) are properly wired.
timestamp: 2026-02-09T18:30:00Z
## Evidence
- timestamp: 2026-02-09T18:20:00Z
checked: n8n error executions (1514, 1516)
found: Both fail at "Prepare Text Action Input" node with error "Paired item data for item from node 'Prepare Action Match Input' is unavailable"
implication: The $('Parse Action Command').item.json reference cannot resolve paired items through the GraphQL chain + sub-workflow call
- timestamp: 2026-02-09T18:25:00Z
checked: Data flow through GraphQL chain
found: Query Containers (1 item) -> Normalize (22 items, one per container) -> Registry Update (22 items) -> Prepare Action Match Input (aggregates to 1 item via $input.all()) -> Execute Action Match (sub-workflow, breaks paired items) -> Route Action Match Result -> Prepare Text Action Input (tries $('Parse Action Command').item.json -> FAILS)
implication: Sub-workflow calls completely reset paired item tracking. Using .item.json to reference nodes before the sub-workflow is invalid.
- timestamp: 2026-02-09T18:30:00Z
checked: Execution 1512 (successful batch keyboard send)
found: "Send Batch Confirmation" (Telegram node) sends message successfully (HTTP 200) but response shows NO inline keyboard buttons. Build Batch Keyboard output has valid reply_markup object.
implication: n8n Telegram node's additionalFields.reply_markup with JSON.stringify() likely double-serializes, causing Telegram to silently ignore the markup
- timestamp: 2026-02-09T18:35:00Z
checked: All reply_markup patterns across all 8 workflow files
found: ALL other nodes that send inline keyboards use HTTP Request nodes with reply_markup as nested object inside JSON.stringify(). Only "Send Batch Confirmation" uses the n8n Telegram node.
implication: The Telegram node approach is unique and broken; HTTP Request pattern works reliably
- timestamp: 2026-02-09T18:40:00Z
checked: Prepare Batch Execution node code
found: Uses $('Detect Batch Command').item.json which has same paired item breakage (downstream of GraphQL chain + Execute Batch Match sub-workflow)
implication: Batch text commands would also fail with paired item error, same root cause as action commands
## Resolution
root_cause: |
TWO distinct root causes, both introduced by Phase 16-06 migration:
1. PAIRED ITEM BREAKAGE: Two Code nodes use $('NodeName').item.json to reference upstream
nodes, but the reference traverses both a GraphQL normalizer chain (which expands 1 item
to 22 items) AND a sub-workflow call (Execute Match), both of which break n8n's paired
item tracking. Affected nodes:
- "Prepare Text Action Input": $('Parse Action Command').item.json
- "Prepare Batch Execution": $('Detect Batch Command').item.json
2. TELEGRAM NODE REPLY_MARKUP: "Send Batch Confirmation" uses n8n Telegram node with
reply_markup in additionalFields set to JSON.stringify($json.reply_markup). The Telegram
node double-serializes this, causing Telegram API to receive an escaped string instead
of a JSON object for reply_markup, so buttons are silently dropped.
fix: |
Three changes to n8n-workflow.json:
1. Prepare Text Action Input: Changed $('Parse Action Command').item.json to .first().json
(.first() doesn't require paired item tracking - it always returns the first output item)
2. Prepare Batch Execution: Changed $('Detect Batch Command').item.json to .first().json
(same fix, same reason)
3. Send Batch Confirmation: Converted from n8n Telegram node to HTTP Request node
(matching the pattern used by ALL other confirmation messages in the project).
New config sends JSON body with reply_markup as a nested object, not double-serialized.
verification: Workflow pushed to n8n (HTTP 200). Awaiting user verification of text commands.
files_changed:
- n8n-workflow.json
+85
View File
@@ -0,0 +1,85 @@
---
status: verifying
trigger: "Single container update via inline keyboard fails with execution errors on both main workflow and container update sub-workflow"
created: 2026-02-09T00:00:00Z
updated: 2026-02-09T00:30:00Z
---
## Current Focus
hypothesis: CONFIRMED - Three bugs in n8n-update.json causing update flow failure
test: Push fixed workflow and trigger update via inline keyboard
expecting: Update should complete without execution errors
next_action: User triggers update to verify fix
## Symptoms
expected: Tapping "Update" on inline keyboard confirmation should trigger container update via GraphQL API
actual: Execution errors on both main workflow and update sub-workflow after confirmation dialog
errors: (1) "Unknown argument 'filter' on field 'Docker.containers'" (2) "missing data.docker.containers" (3) Wrong node reference in Return Error
reproduction: Tap Update on container submenu, confirm, observe error
started: After Phase 16 migration (Docker socket proxy -> Unraid GraphQL API)
## Eliminated
- hypothesis: Credential ID issue (placeholder "unraid-api-key-credential-id")
evidence: n8n resolves credentials by name on push; actual n8n has correct ID "6DB4RZZoeF5Raf7V"
timestamp: 2026-02-09
- hypothesis: ContainerId format is wrong (PrefixedID with colon)
evidence: The PrefixedID format is correct and used by the mutation; the issue is the query using a nonexistent filter arg
timestamp: 2026-02-09
- hypothesis: Main workflow "Prepare Text Action Input" error is related
evidence: Execution 1516 was triggered by text command "Start dup", not an update callback - separate bug
timestamp: 2026-02-09
## Evidence
- timestamp: 2026-02-09
checked: n8n execution 1498 (main workflow, callback update flow)
found: Flow reaches "Execute Callback Update" which calls update sub-workflow; sub-workflow fails with "missing data.docker.containers" error
implication: Error originates in update sub-workflow, propagates back to main workflow
- timestamp: 2026-02-09
checked: n8n execution 1500 (update sub-workflow)
found: "Query Single Container" node sends GraphQL query with `filter: { id: "..." }` argument. Unraid API responds HTTP 400: "Unknown argument 'filter' on field 'Docker.containers'"
implication: The `filter` argument does not exist in Unraid GraphQL API schema. All working queries use `query { docker { containers { ... } } }` without filter
- timestamp: 2026-02-09
checked: Working queries in n8n-actions.json, n8n-status.json
found: All working nodes query ALL containers without filter, then filter client-side
implication: Unraid GraphQL API only supports listing all containers, no server-side filtering
- timestamp: 2026-02-09
checked: Update sub-workflow flow routing
found: Main workflow passes containerId (resolved by name). Sub-workflow's "Has Container ID?" = true, routes to "Query Single Container" (broken filter). The "no container ID" path through "Query All Containers" works correctly
implication: Direct ID path is always taken and always fails
- timestamp: 2026-02-09
checked: "Return Error" node code
found: References `$('Format Pull Error')` but node is actually named "Format Update Error"
implication: Error path would also fail with "node not found" if reached
- timestamp: 2026-02-09
checked: "Capture Pre-Update State" node
found: Reads `data.image` (lowercase) from normalizer but normalizer outputs `Image` (capitalized)
implication: currentImage would always be empty string even if normalizer worked
## Resolution
root_cause: Three bugs in n8n-update.json:
1. PRIMARY: "Query Single Container" uses nonexistent GraphQL `filter` argument on `Docker.containers`. Unraid API does not support server-side filtering - returns HTTP 400.
2. SECONDARY: "Return Error" node references `$('Format Pull Error')` but node is named "Format Update Error" (leftover from pre-migration naming).
3. MINOR: "Capture Pre-Update State" reads `data.image` but normalizer outputs `data.Image` (case mismatch).
fix: |
1. Changed "Query Single Container" jsonBody from filter-based query to same all-containers query used by working nodes
2. Rewrote "Normalize Single Container" to fetch all containers, then filter client-side by containerId from trigger data
3. Fixed "Return Error" node reference from `$('Format Pull Error')` to `$('Format Update Error')`
4. Fixed "Capture Pre-Update State" property access from `data.image` to `data.Image`
verification: Pushed to n8n (HTTP 200). Awaiting user test of inline keyboard update flow.
files_changed:
- /home/luc/Projects/unraid-docker-manager/n8n-update.json