Skip to content

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

Closed

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.jsonnet → schemaRef('JobStatus')), and the handler reads req.body directly as that string (apps/api/src/routes/v1/workspaces/jobs.ts, updateJobStatus → const { 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.

Activity

  1. adityachoudhari26 commented on Jun 3, 2026

    @adityachoudhari26
    MemberAuthor

    @claude fix this

  2. claude commented on Jun 3, 2026

    @claude

    Claude finished @adityachoudhari26's task in 2m 20s —— View job • claude/issue-1158-20260603-1819 • Create PR ➔


    Fixing job status update endpoint

    • Read relevant files to understand current state
    • Fix OpenAPI schema in jobs.jsonnet
    • Fix handler in jobs.ts to read req.body.status
    • Update generated openapi.json and openapi.ts types
    • Commit and push changes

    Changes made

    The endpoint was broken because express.json strict mode rejects bare top-level strings, but the schema declared the request body as a bare JobStatus string.

    apps/api/openapi/paths/jobs.jsonnet — changed request body from schemaRef('JobStatus') to { type: object, required: ["status"], properties: { status: JobStatus } }

    apps/api/src/routes/v1/workspaces/jobs.ts — changed const { body: oapiStatus } = req to const { status: oapiStatus } = req.body

    apps/api/openapi/openapi.json and apps/api/src/types/openapi.ts — updated generated artifacts to match the new schema

    Now the endpoint accepts:

    curl -X PUT "$API/api/v1/workspaces/$WS/jobs/$JOB/status" \
      -H "x-api-key: $KEY" -H 'content-type: application/json' \
      -d '{"status":"successful"}'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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