Repository navigation
Conversation
Error: {"errors":[{"message":"not found","path":"/v2/openapi.json"}],"method":"GET","msg":"Response OpenAPI validation error","rt":"misc.openApi","statusCode":200.0,"url":"/v2/openapi.json"} (also logged with statusCode 304.0)
Files: apify-api/openapi/paths/tools/openapi.json.yaml:1, apify-api/openapi/openapi.yaml:810, apify-api/openapi/components/tags.yaml:450, apify-api/openapi/components/x-tag-groups.yaml:46
Root cause: The API serves the public, unauthenticated `misc.openApi` route (GET `/v2/openapi.json`) which returns the bundled OpenAPI definition, but the spec had no path for it, so the validator reports every response as "not found". Express sends the body via `res.send`, which adds an `ETag` and answers a matching `If-None-Match` with an empty 304, so the 304 response is documented as well. A new `OpenAPI` tag is added under the "Utility tools" group so the endpoint gets a docs page.
Reference: https://github.com/apify/apify-core/tree/8870ffca6640f3f60e8aeaee328a13f3ac90d8c4/src/api/src/routes/misc/openapi.ts#L17 and https://github.com/apify/apify-core/tree/8870ffca6640f3f60e8aeaee328a13f3ac90d8c4/src/api/src/routes/routes_config.ts#L1398
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contributor
|
🗑️ Preview for this PR was deleted. |
Contributor
|
API behavior and specification alignment:
Reviewed commit: 484c960 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Autogenerated OpenAPI fixes suggestions based on validation errors generated from running API integration tests with OpenAPI validator turned on.
Replaces #3200, which GitHub closed after a branch force-push and will not reopen.
Error log: Production response-validation log exported from Mezmo (
6d31d9db-errors, 318 lines, Oct 30 – Nov 6 2026), supplied manually. There is no public link; the log is not reproducible in the PR test environment.apify-core version: https://github.com/apify/apify-core/tree/8870ffca6640f3f60e8aeaee328a13f3ac90d8c4 (
developat the time the log was processed)Stop reason: The scope of this iteration was limited to endpoints that are completely missing from the spec. Of the three such endpoints in the log, only
GET /v2/openapi.jsonbelongs in the public reference and is added here. The deprecateddirect-upload-urlendpoint and the internalPOST /v2/meta/github-leaked-tokenswebhook stay undocumented on purpose, and the remaining "not found" errors are malformed URLs that Express serves leniently. All of these are skipped in the validator instead, see the companion apify-core branchclaude/funny-ptolemy-phf4wv(commits https://github.com/apify/apify-core/commit/753b48854aa744d6040d3f0822464fec91f1fc98 and https://github.com/apify/apify-core/commit/e72e879303adb3f4bcfb74d6e6182c5bd4e8324f). All other errors in the log are schema errors on existing endpoints and are listed below without fixes.The PR test environment was not run for this change (push to the validator branch was not available in this session). Regression check was done statically: the bundled
openapi.jsonbuilt from this branch differs from the one built frommasteronly by the added path and the added tag (OpenAPI). Every pre-existing path, schema, tag and tag group is unchanged.pnpm openapi:lintpasses.Detailed changes description
Error fixes
Add missing
GET /v2/openapi.jsonapify-api/openapi/paths/tools/openapi.json.yaml:1,apify-api/openapi/openapi.yaml:808,apify-api/openapi/components/tags.yaml:450,apify-api/openapi/components/x-tag-groups.yaml:46{"errors":[{"message":"not found","path":"/v2/openapi.json"}],"method":"GET","msg":"Response OpenAPI validation error","rt":"misc.openApi","statusCode":200.0,"url":"/v2/openapi.json"}(2 occurrences, plus 1 with"statusCode":304.0)misc.openApiroute returns the bundled OpenAPI definition, but the spec had no path for it. The handler sends the document with Expressres.send, which adds anETagheader and answers a matchingIf-None-Matchwith an empty304, so both200and304are documented. A newOpenAPItag is added to the "Utility tools" tag group, because the docs site generates pages per tag group and an operation without a grouped tag would get no page.Refactoring
None.
Unfixed errors
False positives
Requests with a doubled slash after
/v2reported as "not found" (88 occurrences){"errors":[{"message":"not found","path":"/v2//datasets/{datasetId}/items"}],"method":"GET","msg":"Response OpenAPI validation error","rt":"datasets.items","statusCode":200.0,"url":"/v2//datasets/{datasetId}/items?format=json&token=[REDACTED]"}and the same pattern foractorTasks.actorTaskRunList,logs.log,actors.runList,actorRuns.runList,datasets.dataset,users.user,datasets.datasetList,actorTasks.actorTask./v2//datasets/...(the loggedurlisreq.originalUrl, which internal rewrites never change). Express mounts the API router withapp.use('/v2', ...), and its mount matching consumes the optional slash after the prefix, so/v2//datasets/xreaches the router as/datasets/xand is served normally. The validator middleware runs at app level before that mount and express-openapi-validator 5.6.2 matches spec routes by regex against the rawreq.originalUrl, so/v2//datasets/xmatches nothing. The spec cannot and should not describe doubled slashes. Handled in apify-core: the validator now skips URLs with repeated slashes (https://github.com/apify/apify-core/commit/753b48854aa744d6040d3f0822464fec91f1fc98).Misspelled
runs/last-successdedserved asruns/last(3 occurrences){"errors":[{"message":"not found","path":"/v2/actors/apify~facebook-marketplace-scraper/runs/last-successded/dataset/items"}],"method":"GET","msg":"Response OpenAPI validation error","rt":"datasets.items","statusCode":200.0,"url":"/v2/actors/apify~facebook-marketplace-scraper/runs/last-successded/dataset/items?token=[REDACTED]"}/actors/:actorId/runs/last*(and/actor-tasks/:actorTaskId/runs/last*), so any segment starting withlastis served aslast. The spec documents onlyruns/last, which is the intended contract. Handled in apify-core: the validator now skips paths with a suffix glued toruns/last(https://github.com/apify/apify-core/commit/753b48854aa744d6040d3f0822464fec91f1fc98). Tightening the route pattern itself is a separate decision, see Potential API bugs.Paths with a URL-encoded query string (
...runs/last/dataset/items%3Ftoken%3D..., 8 occurrences,401){"errors":[{"message":"not found","path":"/v2/actor-tasks/{actorTaskId}/runs/last/dataset/items%3Ftoken%3D[REDACTED]"}],"method":"GET","msg":"Response OpenAPI validation error","rt":"actorTasks.runLastRouter","statusCode":401.0,"url":"/v2/actor-tasks/{actorTaskId}/runs/last/dataset/items%3Ftoken%3D[REDACTED]"}?of its query string, so the token became part of the last path segment and the request was rejected with401. Client bug, nothing to document. Handled in apify-core: the validator now skips paths containing a percent-encoded?(https://github.com/apify/apify-core/commit/753b48854aa744d6040d3f0822464fec91f1fc98).POST /v2/meta/github-leaked-tokens(2 occurrences,204){"errors":[{"message":"not found","path":"/v2/meta/github-leaked-tokens"}],"method":"POST","msg":"Response OpenAPI validation error","rt":"meta.githubLeakedTokens","statusCode":204.0,"url":"/v2/meta/github-leaked-tokens"}/v2/metais now on the validator's list of paths intentionally absent from the spec (https://github.com/apify/apify-core/commit/753b48854aa744d6040d3f0822464fec91f1fc98).GET /v2/key-value-stores/{storeId}/records/{recordKey}/direct-upload-url(56 occurrences,201){"errors":[{"message":"not found","path":"/v2/key-value-stores/{storeId}/records/{recordKey}/direct-upload-url"}],"method":"GET","msg":"Response OpenAPI validation error","rt":"keyValueStores.recordDirectUploadUrl","statusCode":201.0,"url":"/v2/key-value-stores/{storeId}/records/{recordKey}/direct-upload-url?token=[REDACTED]"}Potential API bugs
runs/last*wildcard routes accept arbitrary suffixesruns/last-successdederror as above.last*route pattern makes a typo in the URL silently return the last run's data. The pattern should probably only acceptlastfollowed by/or the end of the path.direct-upload-urlreturns the raw store document and201on aGETdirect-upload-urlerror as above.transformObjectand the published-fields projection, so the response carries_idinstead ofidand internal fields such asnameLowerCase,accessibleByUserIds,statsAccounted,schemaHashand rawstats. It also answers201 Createdto aGETthat creates nothing, which is not what RFC 9110 §15.3.2 describes.Out of scope errors
Schema errors on existing endpoints (not in this iteration's scope)
GET /v2/storemust be stringat/response/data/items/{n}/categories/0(126) andmust be arrayat/response/data/items/{n}/categories(24);GET /v2/actors/{actorId}must be stringat/response/data/categories/0(1);GET /v2/request-queues/{queueId}andPOST /v2/request-queuesmust be >= 0at/response/data/totalRequestCount(26);POST /v2/actorsno schema defined for status code '409'(7);POST /v2/actor-runs/{runId}/rebootand/metamorphmust be stringat/response/data/integrationTracking/appId(7);POST /v2/actor-runs/{runId}/abortmeta.originnot in enum (2);GET /v2/storeno schema defined for status code '402'(1);GET /v2/actors/{actorId}/versions/0.0must be arrayat/response/data/sourceFiles(1).Issues
Partially implements: #2286
Generated by Claude Code