jackwener/OpenCLI · error · CommandExecutionError
Slock task-status succeeded without returning task id ${expe
Error message
Slock task-status succeeded without returning task id ${expectedId}; refusing to report a status row. What it means
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.
Source
Thrown at clis/slock/task-status.js:80
`;
const result = await page.evaluate(`(async () => { ${snippet} })()`);
const rows = dispatchEvaluateResult(result);
return rows.map((t) => {
const task = assertTaskMutationIdentity(t, id, status);
return {
taskId: task.taskId,
taskStatus: task.taskStatus,
assigneeId: t.claimedById ?? t.assigneeId ?? null,
taskNumber: t.taskNumber ?? null,
};
});
},
});
function assertTaskMutationIdentity(t, expectedId, expectedStatus) {
const taskId = t?.id;
if (!taskId) {
throw new CommandExecutionError(`Slock task-status succeeded without returning task id ${expectedId}; refusing to report a status row.`);
}
if (taskId !== expectedId) {
throw new CommandExecutionError(`Slock task-status returned task id ${taskId}, expected ${expectedId}.`);
}
const taskStatus = t.taskStatus ?? t.status;
if (!taskStatus) {
throw new CommandExecutionError(`Slock task-status returned task ${expectedId} without taskStatus.`);
}
if (taskStatus !== expectedStatus) {
throw new CommandExecutionError(`Slock task-status returned status ${taskStatus}, expected ${expectedStatus}.`);
}
return { taskId, taskStatus };
}
View on GitHub (pinned to 49907e53dc)
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.
Example fix
// before const data = dispatchEvaluateResult(result); // after (unwrap a nested task payload before validation) const raw = dispatchEvaluateResult(result); const data = raw?.task ?? raw;
Defensive patterns
Strategy: type-guard
Validate before calling
if (!taskId) throw new Error('task-status requires a task id');
await cli.run(['task-status', taskId]); Type guard
function isTaskWithId(t) { return !!t && typeof t === 'object' && typeof t.id === 'string' && t.id.length > 0; } Try / catch
try {
const rows = await cli.run(['task-status', id]);
} catch (e) {
if (String(e.message).includes('without returning task id')) {
console.error('API returned no task id — inspect raw payload / API version');
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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 `{}`.
Related errors
- Bilibili view API did not return cid/up_mid for ${bvid}
- Boss recommend response did not include zpData.friendList
- Boss geek chat list response did not include zpData.friendLi
- Boss geek friend enrichment response did not include zpData.
- Boss geek history response did not include a message list
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/fcaafa30d08c10d2.
Report an issue: GitHub.