Skip to content

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

Merged
Pijukatel merged 2 commits into
masterfrom
claude/openapi-errors-fix-3nrbfj
Jul 22, 2026
Merged

docs(openapi): Autofix OpenAPI spec validation errors#2794
Pijukatel merged 2 commits into
masterfrom
claude/openapi-errors-fix-3nrbfj

Conversation

@Pijukatel

@Pijukatel Pijukatel commented Jul 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: User-provided production api.log excerpt (SOFT_FAIL response validation errors, Jul 16–21, 2026). The log is not available at a public URL, so the normalized log lines are included below:

Jul 16 10:34:11 apify-api SOFT_FAIL {"errors":[{"errorCode":"required.openapi.validation","message":"must have required property 'requestUrl'","path":"/response/data/requestUrl"}],"method":"GET","msg":"Response OpenAPI validation error","statusCode":200.0,"url":"/v2/webhooks/{webhookId}"}
Jul 20 15:56:30 apify-api SOFT_FAIL {"errors":[{"message":"no schema defined for status code '402' in the openapi spec","path":"/v2/actor-tasks/{actorTaskId}/run-sync?timeout=300&memory=1024&maxItems=20&build=latest&outputRecordKey=OUTPUT&webhooks="}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":402.0,"url":"/v2/actor-tasks/{actorTaskId}/run-sync?timeout=300&memory=1024&maxItems=20&build=latest&outputRecordKey=OUTPUT&webhooks="}
Jul 21 03:20:22 apify-api SOFT_FAIL {"errors":[{"errorCode":"type.openapi.validation","message":"must be string","path":"/response/data/webhook/requestUrl"},{"errorCode":"type.openapi.validation","message":"must be null","path":"/response/data/webhook"},{"errorCode":"anyOf.openapi.validation","message":"must match a schema in anyOf","path":"/response/data/webhook"}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":201.0,"url":"/v2/webhooks/{webhookId}/test?token=[REDACTED]"}
Jul 21 18:01:10 apify-api SOFT_FAIL {"errors":[{"message":"no schema defined for status code '408' in the openapi spec","path":"/v2/actor-tasks/{actorTaskId}/run-sync?token=[REDACTED]&outputRecordKey=OUTPUT"}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":408.0,"url":"/v2/actor-tasks/{actorTaskId}/run-sync?token=[REDACTED]&outputRecordKey=OUTPUT"}

apify-core version: https://github.com/apify/apify-core/commit/446d6faa5a503ddb64447c4b6b758a811b11b397

Stop reason: All 4 unique errors from the provided log that are still present on master are fixed. The remaining 4 unique errors in the log were already fixed on master by #2785 (the log lines predate that merge, see Out of scope errors). The original errors cannot be reproduced in the PR test environment (they come from production traffic: non-HTTP webhooks, platform usage limits, sync-run timeouts), so they were verified against apify-core source instead. A regression run of the integration tests with the fixed spec completed with status SUCCESS (validator run results) and its api.log contains zero response validation errors; the remaining request validation errors in that log are deliberate malformed-request tests or pre-existing request-side spec gaps unrelated to this diff.

Detailed changes description

Error fixes

Webhook object no longer requires requestUrl

  • Files: apify-api/openapi/components/schemas/webhooks/Webhook.yaml:2
  • Error: must have required property 'requestUrl' at /response/data/requestUrl, GET /v2/webhooks/{webhookId}, status 200
  • Root cause: requestUrl is optional in apify-core and enforced only for webhooks with actionType HTTP_REQUEST. Webhooks with other action types (Slack message, Google Mail, Google Drive, GitHub issue) are stored without requestUrl, and the API response projection (lodash pick) omits missing keys, so the endpoint legitimately returns a webhook object without requestUrl. A clarifying description was added to the property.
  • Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/schemas/src/webhooks.ts#L315

Webhook summary in webhook dispatch allows null requestUrl

  • Files: apify-api/openapi/components/schemas/webhook-dispatches/WebhookDispatchWebhookSummary.yaml:10
  • Error: must be string at /response/data/webhook/requestUrl, POST /v2/webhooks/{webhookId}/test, status 201
  • Root cause: The test-webhook endpoint embeds the stored webhook into the created dispatch and the response projection includes webhook.requestUrl. Webhook create/update accepts requestUrl as nullish (z.string().nullish()), so non-HTTP webhooks can be stored with an explicit null value, which is then returned inside the dispatch's webhook summary. The type was widened to [string, "null"] and a clarifying description was added to the property.
  • Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/zod-types/src/common/webhooks.ts#L57

Add 402 response to POST /v2/actor-tasks/{actorTaskId}/run-sync

  • Files: apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}@run-sync.yaml:144
  • Error: no schema defined for status code '402' in the openapi spec, POST /v2/actor-tasks/{actorTaskId}/run-sync, status 402 (3 occurrences in the log)
  • Root cause: Launching a task run enforces platform usage limits which throw 402 Payment Required errors (Actor memory limit exceeded, concurrent runs limit exceeded, not enough usage to run paid Actor). Sibling run-sync endpoints already document 402 via the shared PaymentRequired response component.
  • Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/errors/src/errors/actor.ts#L5

Add 408 response to POST /v2/actor-tasks/{actorTaskId}/run-sync

  • Files: apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}@run-sync.yaml:152
  • Error: no schema defined for status code '408' in the openapi spec, POST /v2/actor-tasks/{actorTaskId}/run-sync, status 408
  • Root cause: The run-sync handler throws run-timeout-exceeded with status 408 when the run does not reach a terminal status within the maximum synchronous wait time. The GET operation of the same path and all sibling run-sync endpoints already document 408 via the shared Timeout response component.
  • Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/api/src/routes/actor_tasks/run_sync.ts#L68

Refactoring

None. Only shared response components (PaymentRequired.yaml, Timeout.yaml) are re-used; no structural changes.

Unfixed errors

Out of scope errors

POST /v2/actors/{actorId}/builds — no schema for status 402

POST /v2/actor-tasks — no schema for status 404

GET /v2/actors/{actorId}taggedBuilds buildNumber type error

PUT /v2/actor-tasks/{actorTaskId} — no schema for status 409

Issues

Partially implements: #2286

Fix 1: Webhook object no longer requires requestUrl

Error: Jul 16 10:34:11 apify-api SOFT_FAIL {"errors":[{"errorCode":"required.openapi.validation","message":"must have required property 'requestUrl'","path":"/response/data/requestUrl"}],"method":"GET","msg":"Response OpenAPI validation error","statusCode":200.0,"url":"/v2/webhooks/{webhookId}"}
Files: apify-api/openapi/components/schemas/webhooks/Webhook.yaml:2
Root cause: requestUrl is optional in apify-core and enforced only for webhooks with actionType HTTP_REQUEST. Webhooks with other action types (Slack message, Google Mail, Google Drive, GitHub issue) are stored without requestUrl, and the API response projection (lodash pick) omits missing keys, so GET /v2/webhooks/{webhookId} legitimately returns a webhook object without requestUrl.
Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/schemas/src/webhooks.ts#L315

Fix 2: Webhook summary in webhook dispatch allows null requestUrl

Error: Jul 21 03:20:22 apify-api SOFT_FAIL {"errors":[{"errorCode":"type.openapi.validation","message":"must be string","path":"/response/data/webhook/requestUrl"},{"errorCode":"type.openapi.validation","message":"must be null","path":"/response/data/webhook"},{"errorCode":"anyOf.openapi.validation","message":"must match a schema in anyOf","path":"/response/data/webhook"}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":201.0,"url":"/v2/webhooks/{webhookId}/test?token=<REDACTED>"}
Files: apify-api/openapi/components/schemas/webhook-dispatches/WebhookDispatchWebhookSummary.yaml:10
Root cause: POST /v2/webhooks/{webhookId}/test embeds the stored webhook into the created dispatch and the response projection includes webhook.requestUrl. Webhook create/update accepts requestUrl as nullish, so non-HTTP webhooks can be stored with an explicit null requestUrl, which is then returned inside the dispatch's webhook summary.
Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/zod-types/src/common/webhooks.ts#L57

Fix 3: Add 402 response to POST /v2/actor-tasks/{actorTaskId}/run-sync

Error: Jul 20 15:56:30 apify-api SOFT_FAIL {"errors":[{"message":"no schema defined for status code '402' in the openapi spec","path":"/v2/actor-tasks/{actorTaskId}/run-sync?timeout=300&memory=1024&maxItems=20&build=latest&outputRecordKey=OUTPUT&webhooks="}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":402.0,"url":"/v2/actor-tasks/{actorTaskId}/run-sync?timeout=300&memory=1024&maxItems=20&build=latest&outputRecordKey=OUTPUT&webhooks="}
Files: apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}@run-sync.yaml:144
Root cause: Launching a task run enforces platform usage limits which throw 402 Payment Required errors (actor memory limit, concurrent runs limit, not enough usage to run paid Actor). Sibling run-sync endpoints already document 402 via the shared PaymentRequired response component.
Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/packages/errors/src/errors/actor.ts#L5

Fix 4: Add 408 response to POST /v2/actor-tasks/{actorTaskId}/run-sync

Error: Jul 21 18:01:10 apify-api SOFT_FAIL {"errors":[{"message":"no schema defined for status code '408' in the openapi spec","path":"/v2/actor-tasks/{actorTaskId}/run-sync?token=<REDACTED>&outputRecordKey=OUTPUT"}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":408.0,"url":"/v2/actor-tasks/{actorTaskId}/run-sync?token=<REDACTED>&outputRecordKey=OUTPUT"}
Files: apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}@run-sync.yaml:152
Root cause: The run-sync handler throws run-timeout-exceeded with status 408 when the run does not reach a terminal status within the maximum synchronous wait time. The GET operation of the same path and all sibling run-sync endpoints already document 408 via the shared Timeout response component.
Reference: https://github.com/apify/apify-core/tree/446d6faa5a503ddb64447c4b6b758a811b11b397/src/api/src/routes/actor_tasks/run_sync.ts#L68

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SdZCyJ9vhtU2DKVvQYiNUD
@github-actions github-actions Bot added this to the 145th sprint - Tooling team milestone Jul 22, 2026
@github-actions github-actions Bot added the t-tooling Issues with this label are in the ownership of the tooling team. label Jul 22, 2026
@apify-service-account

apify-service-account commented Jul 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#974

  • 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 Jul 22, 2026 — with Claude
@Pijukatel
Pijukatel requested a review from vdusek July 22, 2026 11:37
@Pijukatel
Pijukatel marked this pull request as ready for review July 22, 2026 11:37
@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:

The companion apify-client-python PR has been updated with the latest spec changes: apify/apify-client-python#974

  • 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 merged commit 4e864e0 into master Jul 22, 2026
16 checks passed
@Pijukatel
Pijukatel deleted the claude/openapi-errors-fix-3nrbfj branch July 22, 2026 12:24
Pijukatel pushed a commit to apify/apify-client-python that referenced this pull request Jul 22, 2026
- Updates the auto-generated Pydantic models and TypedDicts based on the
proposed OpenAPI specification changes.
- Based on apify-docs PR
[#2794](apify/apify-docs#2794).
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