{"record":{"id":"752827df9bb113b1","repo":"apify/crawlee","slug":"the-minconcurrency-maxconcurrency-initialconc","errorCode":null,"errorMessage":"The `minConcurrency`/`maxConcurrency`/`initialConcurrency`/`maxRequestsPerMinute` shortcuts cannot be combined with `concurrencySystem` - they configure the default `ConcurrencySystem` that a supplied one replaces. Pass them to the `ConcurrencySystem` constructor instead.","messagePattern":"The `minConcurrency`/`maxConcurrency`/`initialConcurrency`/`maxRequestsPerMinute` shortcuts cannot be combined with `concurrencySystem` - they configure the default `ConcurrencySystem` that a supplied one replaces\\. Pass them to the `ConcurrencySystem` constructor instead\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/basic-crawler/src/internals/basic-crawler.ts","lineNumber":1039,"sourceCode":"            statusMessageLoggingInterval,\n            statusMessageCallback,\n            statistics,\n            httpClient,\n\n            id,\n        } = parsedOptions;\n\n        // All concurrency configuration lives on the `ConcurrencySystem`, so the shortcuts have nowhere to go once\n        // one is supplied - and silently dropping a `maxConcurrency` the user asked for is how crawls end up\n        // hammering a site.\n        if (\n            concurrencySystem !== undefined &&\n            (minConcurrency !== undefined ||\n                maxConcurrency !== undefined ||\n                initialConcurrency !== undefined ||\n                maxRequestsPerMinute !== undefined)\n        ) {\n            throw new Error(\n                'The `minConcurrency`/`maxConcurrency`/`initialConcurrency`/`maxRequestsPerMinute` shortcuts ' +\n                    'cannot be combined with `concurrencySystem` - they configure the default `ConcurrencySystem` ' +\n                    'that a supplied one replaces. Pass them to the `ConcurrencySystem` constructor instead.',\n            );\n        }\n\n        // Create per-crawler service locator if custom services were provided.\n        // This wraps every method on the crawler instance so that calls to the global `serviceLocator`\n        // (via AsyncLocalStorage) resolve to this scoped instance instead.\n        // We also enter the scope for the rest of the constructor body, so that any code below\n        // that accesses `serviceLocator` will see the correct (scoped) instance.\n        let serviceLocatorScope = { enterScope: () => {}, exitScope: () => {} };\n\n        if (\n            storageBackend ||\n            eventManager ||\n            logger ||\n            (configuration !== undefined && configuration !== serviceLocator.getConfiguration())","sourceCodeStart":1021,"sourceCodeEnd":1057,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/basic-crawler/src/internals/basic-crawler.ts#L1021-L1057","documentation":"BasicCrawler accepts either a custom `concurrencySystem` or the legacy convenience shortcuts (`minConcurrency`, `maxConcurrency`, `initialConcurrency`, `maxRequestsPerMinute`) that configure the built-in default ConcurrencySystem. Passing both is contradictory because the shortcuts would configure a system the custom one replaces, so the constructor rejects it at startup.","triggerScenarios":"Calling `new BasicCrawler({ concurrencySystem: mySystem, maxConcurrency: 5 })` (or with any of minConcurrency/initialConcurrency/maxRequestsPerMinute) while also supplying a concurrencySystem.","commonSituations":"Migrating from shortcut options to a custom ConcurrencySystem and leaving old tuning options in the config object; copying example code that mixes both styles.","solutions":["Remove the shortcut options from the BasicCrawler options object.","Pass minConcurrency/maxConcurrency/initialConcurrency/maxRequestsPerMinute to the ConcurrencySystem constructor and supply that system via `concurrencySystem`."],"exampleFix":"// before\nconst crawler = new BasicCrawler({\n  concurrencySystem: new ConcurrencySystem(),\n  maxRequestsPerMinute: 120,\n});\n// after\nconst crawler = new BasicCrawler({\n  concurrencySystem: new ConcurrencySystem({ maxRequestsPerMinute: 120 }),\n});","handlingStrategy":"validation","validationCode":"const shortcuts = ['minConcurrency', 'maxConcurrency', 'initialConcurrency', 'maxRequestsPerMinute'];\nif (opts.concurrencySystem && shortcuts.some((k) => opts[k] !== undefined)) {\n  throw new Error('Use either concurrencySystem or the concurrency shortcuts, not both.');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one concurrency configuration style per project and stick to it.","When introducing a custom ConcurrencySystem, move all tuning options into its constructor in the same commit.","Keep crawler option objects typed so excess/incompatible keys fail type checks."],"tags":["configuration","concurrency","invalid-options"],"backgroundTag":"conflicting-options","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}