{"record":{"id":"56787a2fb832d013","repo":"Yeachan-Heo/oh-my-codex","slug":"missing-goal-workflow-objective","errorCode":null,"errorMessage":"Missing goal workflow objective.","messagePattern":"Missing goal workflow objective\\.","errorType":"exception","errorClass":"GoalWorkflowError","httpStatus":null,"severity":"error","filePath":"src/goal-workflows/artifacts.ts","lineNumber":128,"sourceCode":"  return join(goalWorkflowDir(cwd, workflow, slug), GOAL_WORKFLOW_STATUS);\n}\n\nexport function goalWorkflowLedgerPath(cwd: string, workflow: string, slug: string): string {\n  return join(goalWorkflowDir(cwd, workflow, slug), GOAL_WORKFLOW_LEDGER);\n}\n\nexport async function appendGoalWorkflowLedger(cwd: string, run: GoalWorkflowRun, entry: GoalWorkflowLedgerEntry): Promise<void> {\n  await mkdir(join(cwd, run.artifactDir), { recursive: true });\n  await appendFile(join(cwd, run.ledgerPath), `${JSON.stringify(entry)}\\n`);\n}\n\nasync function writeRun(cwd: string, run: GoalWorkflowRun): Promise<void> {\n  await mkdir(join(cwd, run.artifactDir), { recursive: true });\n  await writeFile(join(cwd, run.statusPath), `${JSON.stringify(run, null, 2)}\\n`);\n}\n\nexport async function createGoalWorkflowRun(cwd: string, options: CreateGoalWorkflowRunOptions): Promise<GoalWorkflowRun> {\n  if (!options.objective.trim()) throw new GoalWorkflowError('Missing goal workflow objective.');\n  const workflow = normalizeGoalWorkflowSegment(options.workflow);\n  const slug = normalizeGoalWorkflowSegment(options.slug ?? slugFromObjective(options.objective), 'goal-workflow');\n  const statusPath = goalWorkflowStatusPath(cwd, workflow, slug);\n  if (!options.force && existsSync(statusPath)) {\n    throw new GoalWorkflowError(`Refusing to overwrite existing ${repoRelative(cwd, statusPath)}; pass force to recreate it.`);\n  }\n\n  const now = iso(options.now);\n  const artifactDir = repoRelative(cwd, goalWorkflowDir(cwd, workflow, slug));\n  const run: GoalWorkflowRun = {\n    version: 1,\n    workflow,\n    slug,\n    objective: options.objective.trim(),\n    status: 'pending',\n    createdAt: now,\n    updatedAt: now,\n    artifactDir,","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/goal-workflows/artifacts.ts#L110-L146","documentation":"GoalWorkflowError thrown by createGoalWorkflowRun when options.objective is empty after trimming. The objective is the required human-readable goal of the run; without it the workflow has nothing to drive slug generation and status tracking, so creation is refused before any files are written.","triggerScenarios":"Calling createGoalWorkflowRun with objective: '', '   ', or a variable that is undefined/null coerced to whitespace; CLI/form layer submitting an untouched objective field; objective loaded from an empty config key.","commonSituations":"Automation derives the objective from a template variable that wasn't filled in; YAML/JSON config has an empty objective key; whitespace-only input accepted by a UI text field; test fixture left blank.","solutions":["Validate the objective is non-empty after trim before calling createGoalWorkflowRun.","If the objective comes from config, fail fast with a descriptive error naming the missing key.","Default or prompt for the objective in the calling layer when it would be blank.","Add a form/schema-level required constraint so blank objectives never reach the API."],"exampleFix":"// before\nawait createGoalWorkflowRun(cwd, { objective: cfg.objective ?? '' });\n\n// after\nconst objective = (cfg.objective ?? '').trim();\nif (!objective) throw new Error('config.objective is required to create a goal workflow run');\nawait createGoalWorkflowRun(cwd, { objective });","handlingStrategy":"validation","validationCode":"const objective = options.objective?.trim();\nif (!objective) throw new Error('objective is required');\nawait createGoalWorkflowRun(cwd, { ...options, objective });","typeGuard":"function isValidObjective(v: unknown): v is string {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try { await createGoalWorkflowRun(cwd, options); }\ncatch (e) { if (e instanceof GoalWorkflowError && e.message.includes('objective')) {/* prompt user for objective */} else throw e; }","preventionTips":["Mark objective required in your form/config schema.","Fail fast on blank template variables before calling the API.","Unit-test the blank-objective path in your wrapper."],"tags":["validation","empty-input","goal-workflows","typescript"],"backgroundTag":"empty-required-field","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}