Skip to content

PUT /v1/workspaces/{workspaceId}/jobs/{jobId}/status rejects all valid bodies (body-parser strict mode vs bare-string schema) #1158

Description

@adityachoudhari26

Summary

The job status update endpoint PUT /v1/workspaces/{workspaceId}/jobs/{jobId}/status returns 400 for every possible request body. It is currently unusable over HTTP.

Root cause

Two things collide:

  1. apps/api/src/server.ts mounts express.json({ limit: "100mb" }), which uses body-parser's default strict: true — only {…} (objects) and […] (arrays) are accepted at the top level.
  2. The endpoint's OpenAPI request body is a bare JobStatus string (apps/api/openapi/paths/jobs.jsonnetschemaRef('JobStatus')), and the handler reads req.body directly as that string (apps/api/src/routes/v1/workspaces/jobs.ts, updateJobStatusconst { body: oapiStatus } = req).

So there is no body that works:

  • "successful" (the documented body) → top-level scalar → body-parser throws SyntaxError: Unexpected token '"' before the handler runs.
  • successful (unquoted) → not valid JSON → same class of error.
  • { "status": "successful" } → passes strict mode but fails the handler's oapiToDbStatus[body] lookup → 400 Invalid job status.

Reproduction

curl -s -X PUT "$API/api/v1/workspaces/$WS/jobs/$JOB/status" \
  -H "x-api-key: $KEY" -H 'content-type: application/json' -d '"successful"'
# {"message":"Unexpected token '\"', \"\"successful\"\" is not valid JSON","code":"SyntaxError",...}

Why it has gone unnoticed

Job status is updated today via paths that bypass this endpoint:

  • the workspace-engine writes the DB directly (UpdateJobStatus query), and
  • the GitHub / Terraform Cloud / Argo webhooks write the DB directly.

Nothing currently drives this HTTP endpoint, so the breakage has been silent.

Why it matters now

The pull-based job agent (#1153 / PR #1157) has external agents report status over HTTP via this endpoint — it is the "report status back" half of the pull contract. The endpoint must work for pull agents to function.

Proposed fix

Change the request body from a bare string to an object and read it accordingly:

  • OpenAPI: request body schema → { type: object, required: ["status"], properties: { status: JobStatus } }
  • Handler: const { status } = req.body instead of const oapiStatus = req.body

Object bodies pass strict mode, it's conventional REST, and since there are no working callers today there is nothing to break. (Rejected alternatives: express.json({ strict: false }) globally — too broad; a per-route text parser — hacky.)

Regenerate the API OpenAPI types after the schema change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions