{"record":{"id":"8123b361cd8aa4c2","repo":"paperclipai/paperclip","slug":"session-goal-set-requires-an-objective-or-active-p","errorCode":null,"errorMessage":"session.goal.set requires an objective or active/paused status","messagePattern":"session\\.goal\\.set requires an objective or active/paused status","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts","lineNumber":464,"sourceCode":"  if (request.command === \"session.goal.get\") {\n    const activeHost = requireHost();\n    return observedGoalProjection(activeHost.goalCapability(), activeHost.goalSnapshot(), turnId !== null);\n  }\n  if (request.command === \"session.goal.set\") {\n    const activeHost = requireHost();\n    if (Object.prototype.hasOwnProperty.call(request.params, \"tokenBudget\")) {\n      throw new Error(\"The negotiated ACP goal extension does not support token budget control\");\n    }\n    const objective = text(request.params.objective).trim();\n    const status = text(request.params.status).trim();\n    const action = objective\n      ? \"set\"\n      : status === \"paused\"\n        ? \"pause\"\n        : status === \"active\"\n          ? \"resume\"\n          : null;\n    if (!action) throw new Error(\"session.goal.set requires an objective or active/paused status\");\n    const goal = await activeHost.controlGoal(action, objective || undefined);\n    return observedGoalProjection(activeHost.goalCapability(), goal, turnId !== null);\n  }\n  if (request.command === \"session.goal.clear\") {\n    const activeHost = requireHost();\n    await activeHost.controlGoal(\"clear\");\n    return observedGoalProjection(activeHost.goalCapability(), null, turnId !== null);\n  }\n  if (request.command === \"session.suspend\") {\n    if (turnId || tools.size > 0 || inputs.size > 0) {\n      throw new Error(\"ACPX session is not at a safe suspension point\");\n    }\n    // Cleanup retries must be able to reach the retained host. The command is\n    // still serialized, and retainActiveHostCleanup keeps admission closed\n    // until one sequential close proves ownership was released.\n    const activeHost = requireHost({ allowCleanupRetry: true });\n    const identity = acpxProviderSessionIdentity(\n      activeHost.identity(),","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts#L446-L482","documentation":"The session.goal.set command needs enough information to derive an action: either a non-empty objective ('set') or a status of 'paused' ('pause') or 'active' ('resume'). The sidecar parses these fields and throws when it cannot map them to any action.","triggerScenarios":"Dispatching session.goal.set where params.objective is empty/whitespace and params.status is not exactly 'paused' or 'active' (e.g. empty, 'running', 'stop').","commonSituations":"Passing status values from an app-level enum that doesn't match the ACP vocabulary; calling goal.set with only a token budget (also rejected) or blank fields after trimming.","solutions":["Pass a non-empty objective string in params.objective","Or pass params.status as exactly 'active' or 'paused'","Normalize the caller's status enum to the ACP vocabulary before dispatch"],"exampleFix":"// before\nhost.dispatch({ command: 'session.goal.set', params: { status: 'running' } });\n// after\nhost.dispatch({ command: 'session.goal.set', params: { status: 'active' } });","handlingStrategy":"validation","validationCode":"function canDispatchGoalSet(p) { return Boolean((p.objective ?? '').trim()) || ['active','paused'].includes(p.status); }\nif (!canDispatchGoalSet(params)) throw new Error('goal.set needs objective or active/paused status');","typeGuard":"function isValidGoalSetParams(p: { objective?: string; status?: string }): boolean {\n  return Boolean(p.objective?.trim()) || p.status === 'active' || p.status === 'paused';\n}","tryCatchPattern":"try { await host.dispatch({ command: 'session.goal.set', params }); }\ncatch (e) { if (String(e.message).includes('requires an objective')) { /* prompt user for objective or correct status */ } else throw e; }","preventionTips":["Map your app's status enum to the ACP vocabulary ('active'/'paused') at the boundary","Trim and check objective before dispatching","Only call goal.set when there is something to set; use goal.clear otherwise"],"tags":["acp","validation","empty-required-field"],"backgroundTag":"empty-required-field","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}