docs(openapi): Autofix OpenAPI spec validation errors#2670
Conversation
…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
|
🗑️ Preview for this PR was deleted. |
|
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 A companion PR has been opened in
|
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
c7e8ad1 to
f83c753
Compare
|
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 A companion PR has been opened in
|
This PR updates the auto-generated Pydantic models and TypedDicts based on OpenAPI specification changes in [apify-docs PR #2670](apify/apify-docs#2670).
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-allowedto the ErrorType enumapify-api/openapi/components/schemas/common/ErrorType.yaml:311Response 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"}]}service-workerrequest header is blocked with HTTP 403 and the error typeservice-worker-registration-not-allowed. That value was missing from theErrorTypeenum, 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).Document the
statusquery parameter on the last-run log endpointsapify-api/openapi/components/objects/logs/log.yaml:103,apify-api/openapi/components/objects/logs/log.yaml:120Request OpenAPI validation error {"url":"/v2/actor-tasks/{actorTaskId}/runs/last/log?status=SUCCEEDED","method":"GET","errors":[{"path":"/query/status","message":"Unknown query parameter 'status'"}]}/runs/last*route (including/runs/last/log) is served bylastRunRouter, which reads and validates thestatusquery parameter and uses it to select the last run before its log is returned. ThegetLastRunandgetTaskLastRunoperations did not declarestatus, so valid requests using it were rejected. The baseruns/lastendpoint already documents the samestatusLastRunparameter.Use
RequestWithoutIdfor the request-queue update request bodyapify-api/openapi/components/objects/request-queues/request-queue-request.yaml:109Request 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"}]}idfrom the request body ("it's computed from uniqueKey always") and validates againstRequestSchema, which requires onlyuniqueKeyandurl;requestIdis read from the URL path, not the body. The PUT body must therefore not requireid. Because the sharedRequestschema also backs the single-request and list responses (whereidis always present), the PUT body now reuses the existingRequestWithoutIdschema — exactly as the add-requestPOSTalready does — instead of relaxingRequest, so the response contracts stay unchanged.Refactoring
None.
Unfixed errors
False positives
Nullable date-time fields rejected as "must be string,null"
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 equivalentlyfinishedAtonPOST /v2/actor-builds/{buildId}/abort,startedAt/finishedAtonGET /v2/webhook-dispatches/{dispatchId}calls, andnextRunAt/lastRunAton schedules.type: [string, "null"]+format: date-timefield holdsnull. These fields are legitimately nullable in apify-core (an unfinished build/run hasfinishedAt = null, a schedule may havenextRunAt = null). This is the documented validator false positive; the schemas are correct and are left unchanged.taggedBuildsanyOf reported as "must be null" / "must match a schema in anyOf"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}"}]}taggedBuilds(and each tagged build) is modelled asanyOf: [object, null], and eachActorTaggedBuildcontains a nullablefinishedAt. When the validator wrongly rejectsfinishedAt: null, the object branch fails, thenullbranch is then tried, and the wholeanyOfis reported as failing. The schema is correct.Out of scope errors
Intentional negative tests (deliberately malformed requests)
/body/generalAccessmust be string/ invalid enum (tests send'invalid',0,null);/body/eventTypes/{i}enum (MISSED_EVENT_TYPE);/body/handledAtmust match format "date-time"('not-a-date');/body/options/timeoutSecsmust be integer,null('bbb');/query/filter/{i}enum (filter=pending,invalid); missing requiredactIdonPOST /v2/actor-tasks; missing requiredtargetActorIdon metamorph;415media-type tests forPOST /v2/actorsandPOST /v2/tools/encode-and-sign; dataset itemsmust be object(item-validation path).Test-harness, method and meta-endpoint artifacts
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.Issues
Partially implements: #2286