Skip to content

docs(openapi): Autofix OpenAPI spec validation errors#2670

Merged
Pijukatel merged 3 commits into
masterfrom
claude/amazing-davinci-i4qm1x
Jun 23, 2026
Merged

docs(openapi): Autofix OpenAPI spec validation errors#2670
Pijukatel merged 3 commits into
masterfrom
claude/amazing-davinci-i4qm1x

Conversation

@Pijukatel

@Pijukatel Pijukatel commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Autogenerated OpenAPI fixes suggestions based on validation errors generated from running API integration tests with OpenAPI validator turned on.

Error log: https://apify-pr-test-env-logs.s3.us-east-1.amazonaws.com/apify/apify-core/27741/api-80c58e9c104959349635419c82b6e5174b16ded3.html

apify-core version: https://github.com/apify/apify-core/commit/6f157da99ca076e5f3f1da67f507e885d6aeafe8

Stop reason: No new fixes possible. Three genuine spec/API mismatches were fixed; every other validation error in the log is a known validator false positive, an intentional negative test, or an out-of-scope artifact (all documented below).

Detailed changes description

Error fixes

Add service-worker-registration-not-allowed to the ErrorType enum

  • Files: apify-api/openapi/components/schemas/common/ErrorType.yaml:311
  • Error: Response OpenAPI validation error {"url":"/v2/key-value-stores/{storeId}/records/sw.js","method":"GET","statusCode":403,"errors":[{"message":"must be equal to one of the allowed values: 3d-secure-auth-failed, access-right-already-exists, ... [truncated]","errorCode":"enum.openapi.validation","path":"/response/error/type"}]}
  • Root cause: Fetching a key-value store record with a service-worker request header is blocked with HTTP 403 and the error type service-worker-registration-not-allowed. That value was missing from the ErrorType enum, so the validator rejected the (correct) error response body. An integration test asserts this exact error type (tests/integration/tests/key_value_stores/key_value_store.record.js).
  • Reference: https://github.com/apify/apify-core/tree/6f157da99ca076e5f3f1da67f507e885d6aeafe8/src/packages/errors/src/errors/api.ts#L158

Document the status query parameter on the last-run log endpoints

  • Files: apify-api/openapi/components/objects/logs/log.yaml:103, apify-api/openapi/components/objects/logs/log.yaml:120
  • Error: Request OpenAPI validation error {"url":"/v2/actor-tasks/{actorTaskId}/runs/last/log?status=SUCCEEDED","method":"GET","errors":[{"path":"/query/status","message":"Unknown query parameter 'status'"}]}
  • Root cause: Every /runs/last* route (including /runs/last/log) is served by lastRunRouter, which reads and validates the status query parameter and uses it to select the last run before its log is returned. The getLastRun and getTaskLastRun operations did not declare status, so valid requests using it were rejected. The base runs/last endpoint already documents the same statusLastRun parameter.
  • Reference: https://github.com/apify/apify-core/tree/6f157da99ca076e5f3f1da67f507e885d6aeafe8/src/api/src/routes/actors/last_run.ts#L21

Use RequestWithoutId for the request-queue update request body

  • Files: apify-api/openapi/components/objects/request-queues/request-queue-request.yaml:109
  • Error: Request OpenAPI validation error {"url":"/v2/actor-runs/{runId}/request-queue/requests/{requestId}?token=[REDACTED]","method":"PUT","errors":[{"message":"must have required property 'id'","errorCode":"required.openapi.validation","path":"/body/id"}]}
  • Root cause: The update-request handler deletes id from the request body ("it's computed from uniqueKey always") and validates against RequestSchema, which requires only uniqueKey and url; requestId is read from the URL path, not the body. The PUT body must therefore not require id. Because the shared Request schema also backs the single-request and list responses (where id is always present), the PUT body now reuses the existing RequestWithoutId schema — exactly as the add-request POST already does — instead of relaxing Request, so the response contracts stay unchanged.
  • Reference: https://github.com/apify/apify-core/tree/6f157da99ca076e5f3f1da67f507e885d6aeafe8/src/api/src/routes/request_queues/request.ts#L189

Refactoring

None.

Unfixed errors

False positives

Nullable date-time fields rejected as "must be string,null"

  • Error: Response OpenAPI validation error {"url":"/v2/actors/{actorId}","method":"GET","statusCode":200,"errors":[{"message":"must be string,null","errorCode":"type.openapi.validation","path":"/response/data/taggedBuilds/{tag}/finishedAt"}]} — and equivalently finishedAt on POST /v2/actor-builds/{buildId}/abort, startedAt/finishedAt on GET /v2/webhook-dispatches/{dispatchId} calls, and nextRunAt/lastRunAt on schedules.
  • Root cause: The validator incorrectly raises a type error when a type: [string, "null"] + format: date-time field holds null. These fields are legitimately nullable in apify-core (an unfinished build/run has finishedAt = null, a schedule may have nextRunAt = null). This is the documented validator false positive; the schemas are correct and are left unchanged.
  • Reference: https://github.com/apify/apify-core/tree/6f157da99ca076e5f3f1da67f507e885d6aeafe8/src/packages/types/src/schedules.ts#L80

taggedBuilds anyOf reported as "must be null" / "must match a schema in anyOf"

  • Error: Response OpenAPI validation error {"url":"/v2/actors/{actorId}","method":"GET","statusCode":200,"errors":[{"message":"must match a schema in anyOf","errorCode":"anyOf.openapi.validation","path":"/response/data/taggedBuilds/{tag}"}]}
  • Root cause: Cascade of the nullable date-time false positive above. taggedBuilds (and each tagged build) is modelled as anyOf: [object, null], and each ActorTaggedBuild contains a nullable finishedAt. When the validator wrongly rejects finishedAt: null, the object branch fails, the null branch is then tried, and the whole anyOf is reported as failing. The schema is correct.
  • Reference: https://github.com/apify/apify-core/tree/6f157da99ca076e5f3f1da67f507e885d6aeafe8/src/packages/types/src/actor.ts#L783

Out of scope errors

Intentional negative tests (deliberately malformed requests)

  • Error: representative cases — /body/generalAccess must be string / invalid enum (tests send 'invalid', 0, null); /body/eventTypes/{i} enum (MISSED_EVENT_TYPE); /body/handledAt must match format "date-time" ('not-a-date'); /body/options/timeoutSecs must be integer,null ('bbb'); /query/filter/{i} enum (filter=pending,invalid); missing required actId on POST /v2/actor-tasks; missing required targetActorId on metamorph; 415 media-type tests for POST /v2/actors and POST /v2/tools/encode-and-sign; dataset items must be object (item-validation path).
  • Root cause: These requests are deliberately malformed by the integration tests to verify the API rejects them, and the tests assert that rejection. The spec already documents the correct contract, so these are not spec defects and must not be changed.

Test-harness, method and meta-endpoint artifacts

  • Error: Unknown query parameter 'method' (e.g. ?method=PoSt, ?method=XXX); OPTIONS/XXX method not allowed; GET /v2/openapi.json not found; GET /v2/actors/{actorId}/oauth-connections not found.
  • Root cause: These originate from the test harness's method-override query parameter and CORS/invalid-method probes, plus internal/meta endpoints that are intentionally not part of the public OpenAPI document. They are not response-schema defects and are out of scope for this autofix pass.

Issues

Partially implements: #2286

claude added 2 commits June 22, 2026 12:41
…e enum

Error: Response OpenAPI validation error {"url":"/v2/key-value-stores/{storeId}/records/sw.js","method":"GET","statusCode":403,"errors":[{"message":"must be equal to one of the allowed values: 3d-secure-auth-failed, access-right-already-exists, ... [truncated]","errorCode":"enum.openapi.validation","path":"/response/error/type"}]}
Files: apify-api/openapi/components/schemas/common/ErrorType.yaml:311
Root cause: Fetching a key-value store record with a service-worker header is rejected with HTTP 403 and error type "service-worker-registration-not-allowed", but that value was missing from the ErrorType enum, so the validator failed the response body.
Reference: https://github.com/apify/apify-core/tree/6f157da99ca076e5f3f1da67f507e885d6aeafe8/src/packages/errors/src/errors/api.ts#L158
Error: Request OpenAPI validation error {"url":"/v2/actor-tasks/{actorTaskId}/runs/last/log?status=SUCCEEDED","method":"GET","errors":[{"path":"/query/status","message":"Unknown query parameter 'status'"}]}
Files: apify-api/openapi/components/objects/logs/log.yaml:103, apify-api/openapi/components/objects/logs/log.yaml:120
Root cause: The runs/last/log endpoints (for both actors and actor tasks) resolve the last run filtered by the status query parameter and then return its log, but the getLastRun and getTaskLastRun operations did not declare the status parameter, so valid requests using it were rejected by the validator.
Reference: https://github.com/apify/apify-core/tree/6f157da99ca076e5f3f1da67f507e885d6aeafe8/src/api/src/routes/actors/last_run.ts#L21
@github-actions github-actions Bot added this to the 143rd sprint - Tooling team milestone Jun 22, 2026
@github-actions github-actions Bot added the t-tooling Issues with this label are in the ownership of the tooling team. label Jun 22, 2026
@apify-service-account

apify-service-account commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

🗑️ Preview for this PR was deleted.

@apify-service-account

Copy link
Copy Markdown
Contributor

Important

Action required@Pijukatel please coordinate this docs PR with the Python API client PR linked below.

Because this PR modifies the OpenAPI specification, the generated models in apify-client-python must be regenerated to stay in sync. This has already been done automatically:

A companion PR has been opened in apify-client-python with the regenerated models: apify/apify-client-python#874

  • Please make sure to review and merge both PRs together to keep the OpenAPI spec and API clients in sync.
  • You can ask for review and help from the Tooling team if needed.

Error: Request OpenAPI validation error {"url":"/v2/actor-runs/{runId}/request-queue/requests/{requestId}?token=[REDACTED]","method":"PUT","errors":[{"message":"must have required property 'id'","errorCode":"required.openapi.validation","path":"/body/id"}]}
Files: apify-api/openapi/components/objects/request-queues/request-queue-request.yaml:109
Root cause: The update-request handler deletes id from the request body ("it's computed from uniqueKey always") and then validates the body against RequestSchema, which requires only uniqueKey and url; requestId is read from the URL path, not the body. The PUT body therefore must not require id. The shared Request schema requires id and is also used by the single-request and list responses (where id is always present), so instead of relaxing it the PUT body now reuses the existing RequestWithoutId schema, exactly as the add-request POST already does, leaving the response contracts unchanged.
Reference: https://github.com/apify/apify-core/tree/6f157da99ca076e5f3f1da67f507e885d6aeafe8/src/api/src/routes/request_queues/request.ts#L189
@apify-service-account

Copy link
Copy Markdown
Contributor

Important

Action required@Pijukatel please coordinate this docs PR with the Python API client PR linked below.

Because this PR modifies the OpenAPI specification, the generated models in apify-client-python must be regenerated to stay in sync. This has already been done automatically:

A companion PR has been opened in apify-client-python with the regenerated models: apify/apify-client-python#875

  • Please make sure to review and merge both PRs together to keep the OpenAPI spec and API clients in sync.
  • You can ask for review and help from the Tooling team if needed.

@Pijukatel Pijukatel added the adhoc Ad-hoc unplanned task added during the sprint. label Jun 23, 2026
@Pijukatel Pijukatel marked this pull request as ready for review June 23, 2026 08:13
@Pijukatel Pijukatel merged commit 4ba29e4 into master Jun 23, 2026
17 of 18 checks passed
@Pijukatel Pijukatel deleted the claude/amazing-davinci-i4qm1x branch June 23, 2026 11:32
Pijukatel pushed a commit to apify/apify-client-python that referenced this pull request Jun 23, 2026
This PR updates the auto-generated Pydantic models and TypedDicts based
on OpenAPI specification changes in [apify-docs PR
#2670](apify/apify-docs#2670).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants