{"record":{"id":"3195b670ca192927","repo":"n8n-io/n8n","slug":"cannot-pass-an-outputselector-to-method-s","errorCode":null,"errorMessage":"Cannot pass an OutputSelector to .${method}(). ${sourceName}.output(${value.outputIndex}) by itself does not connect anything; chain `.to(target)` on the selector first to produce a connection. Example: .add(${sourceName}.output(${value.outputIndex}).to(targetNode)) — not .add(${sourceName}.output(${value.outputIndex})).to(targetNode).","messagePattern":"Cannot pass an OutputSelector to \\.(.+?)\\(\\)\\. (.+?)\\.output\\((.+?)\\) by itself does not connect anything; chain `\\.to\\(target\\)` on the selector first to produce a connection\\. Example: \\.add\\((.+?)\\.output\\((.+?)\\)\\.to\\(targetNode\\)\\) — not \\.add\\((.+?)\\.output\\((.+?)\\)\\)\\.to\\(targetNode\\)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/workflow-sdk/src/workflow-builder.ts","lineNumber":1277,"sourceCode":"\t\t\t// Note: Composites are handled by tryPluginDispatch at the entry point\n\t\t\tconst alreadyPresent = nodes.has(branch.name);\n\t\t\tconst actualKey = this.addNodeWithSubnodes(nodes, branch);\n\t\t\tif (!alreadyPresent) {\n\t\t\t\tthis.addSingleNodeConnectionTargets(nodes, branch);\n\t\t\t}\n\t\t\t// If the node was renamed, track it and return the actual key\n\t\t\tif (actualKey && actualKey !== branch.name) {\n\t\t\t\teffectiveNameMapping.set(branch.id, actualKey);\n\t\t\t}\n\t\t\treturn actualKey ?? branch.name;\n\t\t}\n\t}\n}\n\nfunction assertNotOutputSelector(value: unknown, method: 'add' | 'to'): void {\n\tif (!isOutputSelector(value)) return;\n\tconst sourceName = value.node.name;\n\tthrow new TypeError(\n\t\t`Cannot pass an OutputSelector to .${method}(). ` +\n\t\t\t`${sourceName}.output(${value.outputIndex}) by itself does not connect anything; ` +\n\t\t\t'chain `.to(target)` on the selector first to produce a connection. ' +\n\t\t\t`Example: .add(${sourceName}.output(${value.outputIndex}).to(targetNode)) ` +\n\t\t\t`— not .add(${sourceName}.output(${value.outputIndex})).to(targetNode).`,\n\t);\n}\n\n/**\n * Helper to check if options is a WorkflowBuilderOptions object\n */\nfunction isWorkflowBuilderOptions(\n\toptions: WorkflowSettings | WorkflowBuilderOptions | undefined,\n): options is WorkflowBuilderOptions {\n\tif (!options) return false;\n\t// WorkflowBuilderOptions has 'settings' or 'registry' as keys\n\t// WorkflowSettings has keys like 'timezone', 'executionOrder', etc.\n\treturn 'settings' in options || 'registry' in options;","sourceCodeStart":1259,"sourceCodeEnd":1295,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/workflow-builder.ts#L1259-L1295","documentation":"An OutputSelector (the object returned by node.output(n)) does not itself perform a connection — it must be terminated with .to(target) to produce a connection. Passing a bare OutputSelector to workflow.add() or workflow.to() is a no-op that the builder explicitly rejects, because the resulting workflow would silently lack the intended wire. The error shows the correct form: chain .to(target) on the selector before passing it to .add().","triggerScenarios":"Writing workflow.add(myNode.output(0)) without the trailing .to(target), or workflow.add(myNode).to(myNode.output(0)) — both leave an unterminated selector. Also triggered when a helper returns node.output(i) and the caller forgets to chain .to().","commonSituations":"Misreading the fluent API examples; partial copy-paste that drops the .to(target) tail; refactoring that splits selector creation from connection.","solutions":["Always terminate an OutputSelector with .to(target): workflow.add(myNode.output(0).to(targetNode)).","Do not pass myNode.output(0) as the target of another .to() — selectors are sources, not destinations."],"exampleFix":"// before\nworkflow.add(myNode.output(0)); // throws\nworkflow.add(trigger({})).to(myNode.output(0)); // also throws\n\n// after\nworkflow.add(myNode.output(0).to(targetNode));","handlingStrategy":"type-guard","validationCode":"import { isOutputSelector } from 'workflow-sdk';\n\nfunction isCompleteConnection(v: unknown): boolean {\n  return !isOutputSelector(v); // a terminated selector is no longer a bare OutputSelector\n}","typeGuard":"import { isOutputSelector } from 'workflow-sdk';\nfunction isBareOutputSelector(v: unknown): boolean {\n  return isOutputSelector(v);\n}","tryCatchPattern":null,"preventionTips":["Always terminate node.output(n) with .to(target) before passing it anywhere.","Never pass an OutputSelector as the destination of .to().","Review fluent chains to confirm every .output() has a chained .to()."],"tags":["workflow-builder","output-selector","connections","api-misuse"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}