{"record":{"id":"4c83ec468a6927ac","repo":"jackwener/OpenCLI","slug":"unknown-pipeline-step-op-at-index-i-check","errorCode":null,"errorMessage":"Unknown pipeline step \"${op}\" at index ${i}. Check the YAML pipeline step name or register the custom step before execution.","messagePattern":"Unknown pipeline step \"(.+?)\" at index (.+?)\\. Check the YAML pipeline step name or register the custom step before execution\\.","errorType":"validation","errorClass":"ConfigError","httpStatus":null,"severity":"error","filePath":"src/pipeline/executor.ts","lineNumber":41,"sourceCode":"  ctx: PipelineContext = {},\n): Promise<unknown> {\n  const args = ctx.args ?? {};\n  const debug = ctx.debug ?? false;\n  let data: unknown = null;\n  const total = pipeline.length;\n\n  try {\n    for (let i = 0; i < pipeline.length; i++) {\n      const step = pipeline[i];\n      if (!step || typeof step !== 'object') continue;\n      for (const [op, params] of Object.entries(step)) {\n        if (debug) debugStepStart(i + 1, total, op, params);\n\n        const handler = getStep(op);\n        if (handler) {\n          data = await executeStepWithRetry(handler, page, params, data, args, op, ctx.stepRetries);\n        } else {\n          throw new ConfigError(\n            `Unknown pipeline step \"${op}\" at index ${i}.`,\n            'Check the YAML pipeline step name or register the custom step before execution.',\n          );\n        }\n\n        if (debug) debugStepResult(data);\n      }\n    }\n  } catch (err) {\n    // Attempt cleanup: release automation tab lease on pipeline failure.\n    if (page?.closeWindow) {\n      try { await page.closeWindow(); } catch { /* ignore */ }\n    }\n    throw err;\n  }\n  return data;\n}\n","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/src/pipeline/executor.ts#L23-L59","documentation":"executePipeline() resolves each YAML pipeline step's operation name to a registered handler via getStep(op). When no handler exists for the step's `op`, it throws this ConfigError telling you the step index and pointing you at either fixing the YAML step name or registering the custom step before execution. This is a configuration/registration error, not a runtime failure.","triggerScenarios":"A YAML pipeline containing a step whose `op` is misspelled (e.g. `clicp: screenshot` instead of `click`) or references a plugin/custom step that was never registered via the step registry before executePipeline (called from runCommand) runs.","commonSituations":"Typo or casing mismatch in pipeline YAML, using a step from a plugin whose registration code was removed or not imported, version upgrade renaming steps, or copy-pasting a pipeline between projects with different registered steps.","solutions":["Check the step name at the given index against the library's documented step list and fix the typo.","Register the custom step (call the registration API for your handler) before invoking executePipeline.","Verify plugin imports/initialization actually run before pipeline execution.","Check release notes for renamed steps after upgrading."],"exampleFix":"// before\nsteps:\n  - op: screeenshot\n// after\nsteps:\n  - op: screenshot\n// or, for custom steps:\nregisterStep('screeenshot', myHandler); // before executePipeline(...)","handlingStrategy":"validation","validationCode":"// Validate all pipeline step names before executing\nfunction validatePipelineSteps(pipeline, knownSteps) {\n  const unknown = [];\n  pipeline.steps.forEach((s, i) => {\n    if (!knownSteps.has(s.op)) unknown.push(`index ${i}: \"${s.op}\"`);\n  });\n  if (unknown.length) throw new Error(`Unknown pipeline steps -> ${unknown.join(', ')}`);\n}\n// validatePipelineSteps(yamlPipeline, new Set(await listRegisteredSteps()));","typeGuard":null,"tryCatchPattern":"try {\n  await executePipeline(pipeline, page, args);\n} catch (e) {\n  if (e instanceof ConfigError && /Unknown pipeline step/.test(e.message)) {\n    const op = e.message.match(/Unknown pipeline step \"([^\"]+)\"/)?.[1];\n    logger.error(`Unregistered step \"${op}\" — check YAML spelling or registerStep(\"${op}\", handler)`);\n    process.exitCode = 2;\n    return;\n  }\n  throw e;\n}","preventionTips":["Validate step ops against the registry at pipeline-load time, before any execution.","Centralize step names as constants/enums instead of hand-typing them in YAML.","Ensure plugin registration modules are imported before runCommand/executePipeline.","Add a CI lint that checks pipeline YAML ops against the current step list after upgrades."],"tags":["configuration","pipeline","yaml"],"backgroundTag":"unknown-pipeline-step","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}