{"record":{"id":"6abafb1d7f982271","repo":"apify/crawlee","slug":"request-object-s-uniquekey-must-be-a-non-empty-str","errorCode":null,"errorMessage":"Request object's uniqueKey must be a non-empty string","messagePattern":"Request object's uniqueKey must be a non-empty string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/storages/request_list.ts","lineNumber":779,"sourceCode":"\n        // Skip requests with duplicate uniqueKey\n        if (!Object.hasOwn(this.#uniqueKeyToIndex, uniqueKey)) {\n            this.#uniqueKeyToIndex[uniqueKey] = this.requests.length;\n            this.requests.push(request);\n        } else if (this.#keepDuplicateUrls) {\n            this.#log.warning(\n                `Duplicate uniqueKey: ${uniqueKey} found while the keepDuplicateUrls option was set. Check your sources' unique keys.`,\n            );\n        }\n    }\n\n    /**\n     * Helper function that validates unique key.\n     * Throws an error if uniqueKey is not a non-empty string.\n     */\n    private ensureUniqueKeyValid(uniqueKey: string): void {\n        if (typeof uniqueKey !== 'string' || !uniqueKey) {\n            throw new Error(\"Request object's uniqueKey must be a non-empty string\");\n        }\n    }\n\n    /**\n     * Checks that a request is currently being processed and throws an error if not.\n     */\n    private ensureInProgress(uniqueKey: string): void {\n        if (!this.inProgress.has(uniqueKey)) {\n            throw new Error(`The request is not being processed (uniqueKey: ${uniqueKey})`);\n        }\n    }\n\n    /**\n     * Throws an error if request list wasn't initialized.\n     */\n    private ensureIsInitialized(): void {\n        if (!this.#isInitialized) {\n            throw new Error(","sourceCodeStart":761,"sourceCodeEnd":797,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/core/src/storages/request_list.ts#L761-L797","documentation":"ensureUniqueKeyValid() enforces that a request's uniqueKey is a non-empty string before it is stored or marked handled. A missing, null, undefined, or empty-string uniqueKey would corrupt the internal uniqueKeyToIndex map and in-progress tracking, so the library refuses it.","triggerScenarios":"Calling markRequestAsHandled() with a request/uniqueKey that is empty or not a string; manually constructing Request-like objects with uniqueKey: '' and adding them via addRequest; overwriting request.uniqueKey to an empty value before adding.","commonSituations":"Copying request objects between queues and clearing uniqueKey; template string uniqueKeys that evaluate to ''; JSON round-trips dropping the field; passing the wrong variable to markRequestAsHandled.","solutions":["Always set uniqueKey via Request.computeUniqueKey(url) or let the library derive it from the URL","Check the request object actually has a non-empty uniqueKey before calling markRequestAsHandled","Use the Request returned from fetchNextRequest rather than hand-built objects when marking handled"],"exampleFix":"// before\nawait requestList.markRequestAsHandled({ url, uniqueKey: '' });\n// after\nimport { Request } from 'crawlee';\nawait requestList.markRequestAsHandled({ url, uniqueKey: Request.computeUniqueKey({ url }) });","handlingStrategy":"validation","validationCode":"function assertUniqueKey(req) {\n  if (typeof req.uniqueKey !== 'string' || !req.uniqueKey) {\n    req.uniqueKey = Request.computeUniqueKey({ url: req.url });\n  }\n}","typeGuard":"function hasValidUniqueKey(r) {\n  return typeof r?.uniqueKey === 'string' && r.uniqueKey.length > 0;\n}","tryCatchPattern":"try {\n  await requestList.markRequestAsHandled(request);\n} catch (err) {\n  if (err.message.includes('uniqueKey must be a non-empty string')) {\n    request.uniqueKey = Request.computeUniqueKey({ url: request.url });\n    await requestList.markRequestAsHandled(request);\n  } else throw err;\n}","preventionTips":["Never hand-assign uniqueKey; let it be computed from the URL","Mark handled only with request objects returned by fetchNextRequest","Check JSON round-trips preserve the uniqueKey field"],"tags":["validation","unique-key","request-list"],"backgroundTag":"invalid-input-type","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}