jackwener/OpenCLI · error · CommandExecutionError

Slock task-status returned task ${expectedId} without taskSt

Error message

Slock task-status returned task ${expectedId} without taskStatus.

What it means

assertTaskMutationIdentity requires the returned task to carry a status (reading `t.taskStatus ?? t.status`). This throw fires when the task object has a matching id but no status field, so the command has nothing to render in its status row. It guards against API payloads that omit the status on success.

Source

Thrown at clis/slock/task-status.js:87

        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. Log the raw task object to confirm which fields the API actually returns.
  2. Update to matching client/server versions so the status field is present.
  3. If the API legitimately omits status, fall back to a follow-up GET /tasks/:id to fetch it.
  4. Fix any mocked/stubbed fixture to include `taskStatus`.

Example fix

// before
return { kind: 'ok', task: { id: task.id } };
// after
return { kind: 'ok', task: { id: task.id, taskStatus: task.status ?? 'unknown' } };
Defensive patterns

Strategy: type-guard

Validate before calling

const t = await fetchTask(id);
if (!('taskStatus' in t) && !('status' in t)) await refetchFullTask(id);

Type guard

function hasTaskStatus(t) { return typeof t?.taskStatus === 'string' || typeof t?.status === 'string'; }

Try / catch

try {
  const rows = await cli.run(['task-status', id]);
} catch (e) {
  if (String(e.message).includes('without taskStatus')) {
    const full = await cli.run(['task-read', id]); // fallback fetch
  } else throw e;
}

Prevention

When it happens

Trigger: task-status succeeds with the correct task id but the payload lacks both `taskStatus` and `status` (partial projection, sparse PATCH response, or a response shape like {id, title} from a different endpoint version).

Common situations: API downgrade/upgrade where the status field was renamed; calling against a proxy that strips fields; mocking a task endpoint with an incomplete fixture.

Related errors


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