{"record":{"id":"69da9dc3f300aca8","repo":"KeygraphHQ/shannon","slug":"pipeline-failed","errorCode":null,"errorMessage":"Pipeline failed","messagePattern":"Pipeline failed","errorType":"exception","errorClass":"PipelineExecutionError","httpStatus":null,"severity":"critical","filePath":"apps/worker/src/temporal/workflows.ts","lineNumber":710,"sourceCode":"    state.error = formatWorkflowError(error, state.currentPhase, state.currentAgent);\n    const errorCode = classifyErrorCode(error);\n    if (errorCode) {\n      state.errorCode = errorCode;\n    }\n    state.summary = computeSummary(state);\n\n    // Log workflow failure summary\n    try {\n      await a.logWorkflowComplete(activityInput, toWorkflowSummary(state, 'failed'));\n    } catch (completionError) {\n      log.warn('Failed to finalize failed workflow', {\n        error: completionError instanceof Error ? completionError.message : String(completionError),\n      });\n    }\n\n    // Carry the populated state so a consumer can report real spend instead of a zeroed\n    // failed state. The original error rides as `cause` for classification/reporting.\n    throw new PipelineExecutionError(state.error ?? 'Pipeline failed', state, { cause: error });\n  }\n}\n\n/** OSS workflow entry point — thin shell around the extracted pipeline function. */\nexport async function pentestPipelineWorkflow(input: PipelineInput): Promise<PipelineState> {\n  return pentestPipeline(input);\n}\n","sourceCodeStart":692,"sourceCodeEnd":718,"githubUrl":"https://github.com/KeygraphHQ/shannon/blob/1ae0a142f8525410a688f0309fd003cc5b1d92de/apps/worker/src/temporal/workflows.ts#L692-L718","documentation":"PipelineExecutionError is the terminal signal thrown by the pentestPipeline Temporal workflow when any unhandled, non-cancellation error escapes the pipeline body. It wraps state.error (or the fallback string 'Pipeline failed') and carries the populated PipelineState (real agentMetrics, completedAgents, summary) plus the original error as cause, so consumers can report actual spend rather than a zeroed failed state. It is thrown only after the workflow finalizes via logWorkflowComplete (which is itself shielded in a try/catch so finalization never blocks the throw).","triggerScenarios":"Any activity or workflow step inside pentestPipeline throws a non-cancellation error that is not caught earlier: a PentestError from an agent activity (e.g. GIT_CHECKPOINT_FAILED, DELIVERABLE_NOT_FOUND, a prompt load failure), a Temporal ApplicationFailure, or an unexpected exception. The top-level catch sets state.status='failed', computes the error code and summary, finalizes, and re-throws as PipelineExecutionError with the original as cause.","commonSituations":"An agent exhausts its retries (3 attempts) and the activity error propagates up. A checkpoint or deliverable operation fails (errors 40/48/49/50). A prompt/config error (41-47) during a phase. A provider/credentials failure that is non-retryable. Disk-full or permission errors during report assembly. The cause field holds the specific underlying error to diagnose.","solutions":["Inspect the thrown PipelineExecutionError.cause and error.state.errorCode/state.error to find the root failure (this is a wrapper, not the root cause).","Match state.currentPhase and state.currentAgent/state.failedAgent to localize which step failed.","Address the underlying error (e.g. clear a git lock, fix a config, free disk) using the specific error's guidance, then resume the workspace.","If state.errorCode indicates a non-retryable config/prompt error, correct the input and start a new run.","Resume with the same workspace name once the root cause is resolved: completed agents are skipped and only the failed phase re-runs.","Check the workflow.log in <workspace>/.shannon/ for the full failure context around state.currentAgent."],"exampleFix":"// before: underlying agent error surfaces only as generic 'Pipeline failed'\n//   try { await client.execute(pentestPipelineWorkflow, input) }\n//   catch (e) { console.log(e.message) }  // 'Pipeline failed'\n// after: unwrap cause and state for actionable detail\n//   catch (e) {\n//     if (e instanceof PipelineExecutionError) {\n//       console.log(e.state.currentPhase, e.state.failedAgent, e.state.errorCode);\n//       console.log(e.cause);  // the real error\n//     }\n//   }","handlingStrategy":"try-catch","validationCode":"// Before the workflow, run preflight checks that cover the most common root causes\nawait preflight(input); // validates model credential, repo path, config schema, prompt existence\n// and ensure disk + git repo health so checkpoint/report activities will not fail mid-pipeline","typeGuard":"function isPipelineExecutionError(e: unknown): e is PipelineExecutionError {\n  return e instanceof PipelineExecutionError && e.name === 'PipelineExecutionError';\n}","tryCatchPattern":"try {\n  const state = await client.execute(pentestPipelineWorkflow, input);\n  return state;\n} catch (e) {\n  if (e instanceof PipelineExecutionError) {\n    // this is a wrapper — diagnose e.cause, e.state.errorCode, e.state.failedAgent, e.state.currentPhase\n    log.error('pipeline failed', {\n      phase: e.state.currentPhase, agent: e.state.failedAgent,\n      code: e.state.errorCode, cause: e.cause,\n    });\n    // fix the root cause (per its specific error), then resume the same workspace\n  }\n  throw e;\n}","preventionTips":["Always read .cause and .state.errorCode on a PipelineExecutionError — the message alone is not actionable.","Run the preflight activity (model probe, config schema, repo path) so config/credential failures surface before the pipeline.","Keep workspaces resumable so a failed pipeline re-runs only the failed phase, not the whole scan.","Monitor workflow.log under <workspace>/.shannon/ for the failure context around state.failedAgent.","For non-retryable error codes (config/prompt/filesystem), fix the input and start a new run rather than retrying unchanged."],"tags":["workflow","temporal","pipeline","error-wrapping","top-level"],"backgroundTag":null,"analyzedSha":"1ae0a142f8525410a688f0309fd003cc5b1d92de","analyzedAt":"2026-08-12T17:40:03.583Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}