{"record":{"id":"7de2aa5bd640d4b9","repo":"coleam00/Archon","slug":"script-node-node-id-stderr-stderr-trim","errorCode":null,"errorMessage":"Script node '${node.id}' stderr:\n```\n${stderr.trim()}\n```","messagePattern":"Script node '(.+?)' stderr:\n```\n(.+?)\n```","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/workflows/src/dag-executor.ts","lineNumber":4122,"sourceCode":"      timeout,\n      env: subprocessEnv,\n      protectedEnvKeys,\n      protectedCredentialValues,\n      retention: {\n        logDir,\n        workflowRunId: workflowRun.id,\n        nodeId: node.id,\n        label: '<script>',\n      },\n    });\n\n    // Trim trailing newline from stdout (common shell behavior)\n    const output = stdout.replace(/\\n$/, '');\n\n    if (stderr.trim()) {\n      getLog().warn({ nodeId: node.id, stderr: stderr.trim() }, 'script_node_stderr');\n      await safeSendMessage(\n        platform,\n        conversationId,\n        `Script node '${node.id}' stderr:\\n\\`\\`\\`\\n${stderr.trim()}\\n\\`\\`\\``,\n        nodeContext\n      );\n    }\n\n    const duration = Date.now() - nodeStartTime;\n    getLog().info({ nodeId: node.id, durationMs: duration }, 'dag_node_completed');\n    await logNodeComplete(logDir, workflowRun.id, node.id, '<script>', { durationMs: duration });\n\n    const persistedOutput = formatPersistedNodeOutput(output, artifactsDir, stepName);\n\n    deps.store\n      .createWorkflowEvent({\n        workflow_run_id: workflowRun.id,\n        event_type: 'node_completed',\n        step_name: stepName,\n        data: {","sourceCodeStart":4104,"sourceCodeEnd":4140,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/dag-executor.ts#L4104-L4140","documentation":"In packages/workflows/src/dag-executor.ts:4122, when a script: node finishes with non-empty stderr, the executor logs 'script_node_stderr' and forwards the stderr to the conversation as a fenced message. Like the bash-node variant, it is informational and does not fail the node by itself.","triggerScenarios":"A script: node's interpreter or code writes anything to stderr — runtime warnings, tracebacks from caught-but-logged errors, dependency deprecation notices — regardless of exit code.","commonSituations":"TypeScript/Python warnings printed on stderr; console.warn/console.error in the script; library logging configured to stderr; unhandled promise rejection messages printed by the runtime.","solutions":["Fix the script source of the stderr output","Route intentional diagnostics to stdout or a log file","Review the run log keyed 'script_node_stderr' for the full output"],"exampleFix":"// node script\n# before\nconsole.error('done processing', n)\n# after\nconsole.log('done processing', n)","handlingStrategy":"validation","validationCode":"// Ensure the script writes no stderr in a pre-run check:\nconst proc = Bun.spawnSync(['bun', 'run', scriptPath]);\nconst noise = proc.stderr.toString().trim();\nif (noise) console.warn('script emits stderr:', noise);","typeGuard":"function isStderrSilent(r: { exitCode: number; stderr: string }): boolean {\n  return r.exitCode === 0 && r.stderr.trim().length === 0;\n}","tryCatchPattern":null,"preventionTips":["Use console.log instead of console.error/warn for informational output","Configure library loggers to stdout or files, not stderr","Run the script standalone once to catch stderr emitters before wiring it into a workflow","Fix genuine runtime warnings rather than suppressing them"],"tags":["script","stderr","workflow","notification"],"backgroundTag":"node-stderr-output","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}