{"record":{"id":"6d3a8687c9a174a8","repo":"apify/crawlee","slug":"at-least-one-of-sources-or-sourcesfunction-mus","errorCode":null,"errorMessage":"At least one of \"sources\" or \"sourcesFunction\" must be provided.","messagePattern":"At least one of \"sources\" or \"sourcesFunction\" must be provided\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/storages/request_list.ts","lineNumber":333,"sourceCode":"    /**\n     * To create new instance of `RequestList` we need to use `RequestList.open()` factory method.\n     * @param options All `RequestList` configuration options\n     * @internal\n     */\n    private constructor(options: RequestListOptions = {}) {\n        const {\n            sources,\n            sourcesFunction,\n            persistStateKey,\n            persistRequestsKey,\n            state,\n            proxyConfiguration,\n            keepDuplicateUrls,\n            httpClient,\n        } = parseArgument(options, requestListOptionsSchema);\n\n        if (!(sources || sourcesFunction)) {\n            throw new Error('At least one of \"sources\" or \"sourcesFunction\" must be provided.');\n        }\n\n        this.#persistStateKey = persistStateKey ? `CRAWLEE_${persistStateKey}` : persistStateKey;\n        this.#persistRequestsKey = persistRequestsKey ? `CRAWLEE_${persistRequestsKey}` : persistRequestsKey;\n        this.#initialState = state;\n        this.#httpClient = httpClient;\n\n        // If this option is set then all requests will get a pre-generated unique ID and duplicate URLs will be kept in the list.\n        this.#keepDuplicateUrls = keepDuplicateUrls;\n\n        // Will be empty after initialization to save memory.\n        this.#sources = sources ? [...sources] : [];\n        this.#sourcesFunction = sourcesFunction;\n\n        // The proxy configuration used for `requestsFromUrl` requests.\n        this.#proxyConfiguration = proxyConfiguration;\n\n        this.persistState = this.persistState.bind(this);","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/core/src/storages/request_list.ts#L315-L351","documentation":"A RequestList must be given its URLs either statically via the sources array or dynamically via sourcesFunction. Constructing one with neither would produce an always-empty list, so the constructor validates and throws immediately.","triggerScenarios":"new RequestList({ sources: undefined, sourcesFunction: undefined }) — e.g. both options omitted, misspelled (source/sources), or computed as undefined by a ternary/config lookup.","commonSituations":"Loading source config from env/JSON that came back empty and was assigned verbatim; renaming options during a refactor; copying an example and deleting both fields while intending to addRequest() later.","solutions":["Pass sources: new RequestList({ sources: ['https://example.com'] })","Or pass sourcesFunction: () => fetchUrls() to generate sources at initialize() time","If requests are added manually later, use RequestQueue instead of RequestList"],"exampleFix":"// before\nconst list = await RequestList.open('list', {});\n// after\nconst list = await RequestList.open('list', { sources: ['https://example.com'] });","handlingStrategy":"validation","validationCode":"function assertRequestListOptions(options) {\n  if (!options.sources && !options.sourcesFunction) {\n    throw new TypeError('RequestList needs \"sources\" or \"sourcesFunction\"');\n  }\n}\nassertRequestListOptions({ sources: config.urls });","typeGuard":"const hasSources = (o) => Array.isArray(o?.sources) && o.sources.length > 0 || typeof o?.sourcesFunction === 'function';","tryCatchPattern":null,"preventionTips":["Never omit both sources and sourcesFunction","Validate config-provided sources arrays are non-empty before constructing","Use RequestQueue if you only add requests dynamically at runtime"],"tags":["validation","request-list","configuration"],"backgroundTag":"missing-required-option","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}