From 8aeca2b7debb9801311defcd18e133500781aed4 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Jul 2026 08:59:44 +0000 Subject: [PATCH 1/2] fix(openapi): add missing 402/404/409 responses and nullable taggedBuilds buildNumber Error: {"errors":[{"message":"no schema defined for status code '402' in the openapi spec","path":"/v2/actors/{actorId}/builds?version=1.0&useCache=false&waitForFinish=180"}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":402} Files: apify-api/openapi/paths/actors/acts@{actorId}@builds.yaml:123 Root cause: POST /v2/actors/{actorId}/builds enforces account memory and concurrent-runs limits before creating the build and throws memory-limit-exceeded/concurrent-runs-limit-exceeded errors with HTTP 402, but the spec did not document a 402 response. Reused the PaymentRequired response component, consistent with the run Actor endpoints that document 402 for the same limit checks. Reference: https://github.com/apify/apify-core/tree/48a50ff1c30b82ade5283e5465ef63a7ec09095b/src/packages/actor-server/src/actor_jobs/actor_jobs.server.ts#L1269 Error: {"errors":[{"message":"no schema defined for status code '404' in the openapi spec","path":"/v2/actor-tasks"}],"method":"POST","msg":"Response OpenAPI validation error","statusCode":404} Files: apify-api/openapi/paths/actor-tasks/actor-tasks.yaml:142 Root cause: POST /v2/actor-tasks looks up the Actor referenced by actId in the request payload and throws record-not-found with HTTP 404 when that Actor does not exist or is removed, but the spec did not document a 404 response. Reused the NotFound response component. Reference: https://github.com/apify/apify-core/tree/48a50ff1c30b82ade5283e5465ef63a7ec09095b/src/api/src/routes/actor_tasks/actor_task_list.ts#L190 Error: {"errors":[{"errorCode":"type.openapi.validation","message":"must be string","path":"/response/data/taggedBuilds/{tag}/buildNumber"},{"errorCode":"anyOf.openapi.validation","message":"must match a schema in anyOf","path":"/response/data/taggedBuilds/{tag}"}],"method":"GET","msg":"Response OpenAPI validation error","statusCode":200,"url":"/v2/actors/{actorId}"} Files: apify-api/openapi/components/schemas/actors/TaggedBuildInfo.yaml:10 Root cause: GET /v2/actors/{actorId} builds the taggedBuilds map via transformActor(), which computes buildNumber as buildOrVersionNumberIntToStr(buildNumberInt) with return type string | null; for legacy builds without a valid buildNumberInt the value is null, while the spec allowed only a string. Allowed null for buildNumber (the pattern keyword only applies to string values in JSON Schema). Reference: https://github.com/apify/apify-core/tree/48a50ff1c30b82ade5283e5465ef63a7ec09095b/src/packages/actor/src/actors/actors.both.ts#L113 Error: {"errors":[{"message":"no schema defined for status code '409' in the openapi spec","path":"/v2/actor-tasks/{actorTaskId}"}],"method":"PUT","msg":"Response OpenAPI validation error","statusCode":409} Files: apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}.yaml:104 Root cause: PUT /v2/actor-tasks/{actorTaskId} throws actor-task-name-not-unique with HTTP 409 when renaming a task to a name already used by another task of the same user (Mongo duplicate key on userId+nameLowerCase), but the spec did not document a 409 response. Reused the Conflict response component, matching POST /v2/actor-tasks which already documents 409 for the same uniqueness constraint. Reference: https://github.com/apify/apify-core/tree/48a50ff1c30b82ade5283e5465ef63a7ec09095b/src/api/src/routes/actor_tasks/actor_task.ts#L151 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_011VY4n4eTrXwjwT4CMsHPJD --- .../openapi/components/schemas/actors/TaggedBuildInfo.yaml | 4 ++-- apify-api/openapi/paths/actor-tasks/actor-tasks.yaml | 2 ++ .../openapi/paths/actor-tasks/actor-tasks@{actorTaskId}.yaml | 2 ++ apify-api/openapi/paths/actors/acts@{actorId}@builds.yaml | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/apify-api/openapi/components/schemas/actors/TaggedBuildInfo.yaml b/apify-api/openapi/components/schemas/actors/TaggedBuildInfo.yaml index 08dfe5dae5..dc1ef70c40 100644 --- a/apify-api/openapi/components/schemas/actors/TaggedBuildInfo.yaml +++ b/apify-api/openapi/components/schemas/actors/TaggedBuildInfo.yaml @@ -7,9 +7,9 @@ properties: description: The ID of the build associated with this tag. examples: [z2EryhbfhgSyqj6Hn] buildNumber: - type: string + type: [string, "null"] pattern: ^([0-9]|[1-9][0-9])\.([0-9]|[1-9][0-9])(\.[1-9][0-9]{0,4})$ - description: The build number/version string. + description: The build number/version string. Can be `null` for legacy builds that lack a valid build number. examples: [0.0.2] buildNumberInt: type: integer diff --git a/apify-api/openapi/paths/actor-tasks/actor-tasks.yaml b/apify-api/openapi/paths/actor-tasks/actor-tasks.yaml index a6b7a0d6a4..a06d64cf63 100644 --- a/apify-api/openapi/paths/actor-tasks/actor-tasks.yaml +++ b/apify-api/openapi/paths/actor-tasks/actor-tasks.yaml @@ -139,6 +139,8 @@ post: $ref: ../../components/responses/Unauthorized.yaml "403": $ref: ../../components/responses/Forbidden.yaml + "404": + $ref: ../../components/responses/NotFound.yaml "405": $ref: ../../components/responses/MethodNotAllowed.yaml "409": diff --git a/apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}.yaml b/apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}.yaml index 5b97dab2b4..4b2d8acde8 100644 --- a/apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}.yaml +++ b/apify-api/openapi/paths/actor-tasks/actor-tasks@{actorTaskId}.yaml @@ -101,6 +101,8 @@ put: $ref: ../../components/responses/NotFound.yaml "405": $ref: ../../components/responses/MethodNotAllowed.yaml + "409": + $ref: ../../components/responses/Conflict.yaml "413": $ref: ../../components/responses/PayloadTooLarge.yaml "415": diff --git a/apify-api/openapi/paths/actors/acts@{actorId}@builds.yaml b/apify-api/openapi/paths/actors/acts@{actorId}@builds.yaml index c8381cf0d6..5ee8b191f8 100644 --- a/apify-api/openapi/paths/actors/acts@{actorId}@builds.yaml +++ b/apify-api/openapi/paths/actors/acts@{actorId}@builds.yaml @@ -120,6 +120,8 @@ post: $ref: ../../components/responses/BadRequest.yaml "401": $ref: ../../components/responses/Unauthorized.yaml + "402": + $ref: ../../components/responses/PaymentRequired.yaml "403": $ref: ../../components/responses/Forbidden.yaml "404": From cd917dc1579639705efecfa0db3bf84cf94d2ae6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Jul 2026 09:29:55 +0000 Subject: [PATCH 2/2] fix(openapi): add cannot-monetize-without-payout-billing-info to ErrorType enum Error: {"url":"/v2/actors/{actorId}","method":"PUT","statusCode":400,"errors":[{"message":"must be equal to one of the allowed values: 3d-secure-auth-failed, access-right-already-exists, ...","errorCode":"enum.openapi.validation","path":"/response/error/type"}]} Files: apify-api/openapi/components/schemas/common/ErrorType.yaml:68 Root cause: PUT /v2/actors/{actorId} with a paid pricing model rejects the update with HTTP 400 and error type cannot-monetize-without-payout-billing-info when the owner has no payout billing info set (thrown by checkAndSanitizePricingInfosModifier), but this error type was missing from the ErrorType enum used by all error responses. Reference: https://github.com/apify/apify-core/tree/48a50ff1c30b82ade5283e5465ef63a7ec09095b/src/api/src/lib/paid_actors_helpers.ts#L364 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_011VY4n4eTrXwjwT4CMsHPJD --- apify-api/openapi/components/schemas/common/ErrorType.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/apify-api/openapi/components/schemas/common/ErrorType.yaml b/apify-api/openapi/components/schemas/common/ErrorType.yaml index efc6eb64be..1d5a155c21 100644 --- a/apify-api/openapi/components/schemas/common/ErrorType.yaml +++ b/apify-api/openapi/components/schemas/common/ErrorType.yaml @@ -65,6 +65,7 @@ enum: - cannot-metamorph-to-pay-per-result-actor - cannot-modify-actor-pricing-too-frequently - cannot-modify-actor-pricing-with-immediate-effect + - cannot-monetize-without-payout-billing-info - cannot-override-paid-actor-trial - cannot-permanently-delete-subscription - cannot-publish-actor