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

  1. Print/inspect the raw response object from the page.evaluate snippet to see the actual payload shape.
  2. If the API nests the task, adjust dispatchEvaluateResult or the snippet to unwrap (e.g. return `res.json()`'s `.task`).
  3. Verify you are on a matching server/API version for the slock tasks endpoints.
  4. 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

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


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/fcaafa30d08c10d2. Report an issue: GitHub.