{"record":{"id":"431822579b40f768","repo":"apify/crawlee","slug":"default-route-is-already-defined-route-for-labe","errorCode":null,"errorMessage":"Default route is already defined! / Route for label '${String(label)}' is already defined!","messagePattern":"Default route is already defined! / Route for label '(.+?)' is already defined!","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/router.ts","lineNumber":443,"sourceCode":"        if (schema) {\n            context.request.userData = (await validateUserData(\n                label!,\n                schema,\n                context.request.userData,\n            )) as GetUserDataFromRequest<Context['request']>;\n        }\n    }\n\n    /**\n     * Throws when the label already exists in our registry.\n     */\n    private validate(label: string | symbol) {\n        if (this.#routes.has(label)) {\n            const message =\n                label === defaultRoute\n                    ? `Default route is already defined!`\n                    : `Route for label '${String(label)}' is already defined!`;\n            throw new Error(message);\n        }\n    }\n\n    /**\n     * Creates new router instance. This instance can then serve as a `requestHandler` of your crawler.\n     *\n     * ```ts\n     * import { Router, CheerioCrawler, CheerioCrawlingContext } from 'crawlee';\n     *\n     * const router = Router.create<CheerioCrawlingContext>();\n     * router.addHandler('label-a', async (ctx) => {\n     *    ctx.log.info('...');\n     * });\n     * router.addDefaultHandler(async (ctx) => {\n     *    ctx.log.info('...');\n     * });\n     *\n     * const crawler = new CheerioCrawler({","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/core/src/router.ts#L425-L461","documentation":"Router.validate (used by addHandler and addDefaultHandler) throws when a route for the given label already exists. The special label for the default route produces the 'Default route is already defined!' message; any other duplicate label produces 'Route for label X is already defined!'. Duplicate registration is treated as a programming error rather than an implicit override.","triggerScenarios":"Calling router.addHandler('products', h) twice, or addDefaultHandler(h) after a default handler was already registered.","commonSituations":"Module executed twice (double import, hot reload) registering routes again; initializing the router in a loop; two code paths both adding a default handler; copy-pasted registration blocks.","solutions":["Register each label only once — guard router setup so it runs a single time","If overriding is intended, recreate the Router or restructure so the new handler replaces the old at setup time","Use distinct labels for distinct handlers","Check for duplicate module initialization (hot reload, multiple entry points)"],"exampleFix":"// before\nrouter.addHandler('detail', handlerA);\nrouter.addHandler('detail', handlerB); // throws\n// after\nrouter.addHandler('detail', handlerA);\nrouter.addHandler('list', handlerB);","handlingStrategy":"try-catch","validationCode":"if (registered.has(label)) return; // skip duplicate registration","typeGuard":null,"tryCatchPattern":"try {\n  router.addHandler(label, handler);\n} catch (err) {\n  if (err.message.includes('already defined')) return; // idempotent setup\n  throw err;\n}","preventionTips":["Guard router setup behind a module-level singleton/flag","Make route registration idempotent (check before add)","Avoid registering routes in loops or hot-reloaded modules","Keep one canonical place where all routes are registered"],"tags":["routing","configuration","duplicate"],"backgroundTag":"duplicate-route-registration","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}