{"record":{"id":"fcaafa30d08c10d2","repo":"jackwener/OpenCLI","slug":"slock-task-status-succeeded-without-returning-task","errorCode":null,"errorMessage":"Slock task-status succeeded without returning task id ${expectedId}; refusing to report a status row.","messagePattern":"Slock task-status succeeded without returning task id (.+?); refusing to report a status row\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/slock/task-status.js","lineNumber":80,"sourceCode":"    `;\n    const result = await page.evaluate(`(async () => { ${snippet} })()`);\n    const rows = dispatchEvaluateResult(result);\n    return rows.map((t) => {\n      const task = assertTaskMutationIdentity(t, id, status);\n      return {\n        taskId: task.taskId,\n        taskStatus: task.taskStatus,\n        assigneeId: t.claimedById ?? t.assigneeId ?? null,\n        taskNumber: t.taskNumber ?? null,\n      };\n    });\n  },\n});\n\nfunction assertTaskMutationIdentity(t, expectedId, expectedStatus) {\n  const taskId = t?.id;\n  if (!taskId) {\n    throw new CommandExecutionError(`Slock task-status succeeded without returning task id ${expectedId}; refusing to report a status row.`);\n  }\n  if (taskId !== expectedId) {\n    throw new CommandExecutionError(`Slock task-status returned task id ${taskId}, expected ${expectedId}.`);\n  }\n  const taskStatus = t.taskStatus ?? t.status;\n  if (!taskStatus) {\n    throw new CommandExecutionError(`Slock task-status returned task ${expectedId} without taskStatus.`);\n  }\n  if (taskStatus !== expectedStatus) {\n    throw new CommandExecutionError(`Slock task-status returned status ${taskStatus}, expected ${expectedStatus}.`);\n  }\n  return { taskId, taskStatus };\n}\n","sourceCodeStart":62,"sourceCodeEnd":94,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/slock/task-status.js#L62-L94","documentation":"The slock task-status CLI calls assertTaskMutationIdentity to validate the task object returned from the API before printing a status row. This throw fires when the API reported success but the returned object has no `id` field at all, so the command cannot prove it mutated/reported the right task. The library treats an unidentified success as a contract violation rather than silently printing a row.","triggerScenarios":"Calling the `task-status` command when the API response object has no `id` property (e.g. `t` is null/undefined, or the endpoint returned a wrapper like {task: {...}} or an error-shaped object that dispatchEvaluateResult passed through).","commonSituations":"Server API version drift where the task payload was renamed or nested; proxies/interceptors stripping the body; the browser snippet hitting a redirect that returned an empty success object; mocking environments returning `{}`.","solutions":["Print/inspect the raw response object from the page.evaluate snippet to see the actual payload shape.","If the API nests the task, adjust dispatchEvaluateResult or the snippet to unwrap (e.g. return `res.json()`'s `.task`).","Verify you are on a matching server/API version for the slock tasks endpoints.","Retry the command; a transient gateway response can yield an empty body masquerading as success."],"exampleFix":"// before\nconst data = dispatchEvaluateResult(result);\n// after (unwrap a nested task payload before validation)\nconst raw = dispatchEvaluateResult(result);\nconst data = raw?.task ?? raw;","handlingStrategy":"type-guard","validationCode":"if (!taskId) throw new Error('task-status requires a task id');\nawait cli.run(['task-status', taskId]);","typeGuard":"function isTaskWithId(t) { return !!t && typeof t === 'object' && typeof t.id === 'string' && t.id.length > 0; }","tryCatchPattern":"try {\n  const rows = await cli.run(['task-status', id]);\n} catch (e) {\n  if (String(e.message).includes('without returning task id')) {\n    console.error('API returned no task id — inspect raw payload / API version');\n  } else throw e;\n}","preventionTips":["Keep CLI and server versions aligned","Log raw API payloads when adding new task endpoints","Never assume a 2xx means a full task object was returned"],"tags":["contract-drift","missing-field","api-response"],"backgroundTag":"api-response-contract-drift","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}