{"record":{"id":"75e39be550dabaaf","repo":"emberjs/ember.js","slug":"defining-a-route-serializer-on-route-name-out","errorCode":null,"errorMessage":"Defining a route serializer on route '${name}' outside an Engine is not allowed.","messagePattern":"Defining a route serializer on route '(.+?)' outside an Engine is not allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@ember/routing/lib/dsl.ts","lineNumber":148,"sourceCode":"    url: string,\n    name: string,\n    callback?: MatchCallback,\n    // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n    serialize?: (model: {}, params: string[]) => { [key: string]: unknown | undefined }\n  ): void {\n    let parts = name.split('.');\n\n    if (this.options.engineInfo) {\n      let localFullName = name.slice(this.options.engineInfo.fullName.length + 1);\n      let routeInfo: EngineRouteInfo = Object.assign({ localFullName }, this.options.engineInfo);\n\n      if (serialize) {\n        routeInfo.serializeMethod = serialize;\n      }\n\n      this.options.addRouteForEngine(name, routeInfo);\n    } else if (serialize) {\n      throw new Error(\n        `Defining a route serializer on route '${name}' outside an Engine is not allowed.`\n      );\n    }\n\n    if (url === '' || url === '/' || parts[parts.length - 1] === 'index') {\n      this.explicitIndex = true;\n    }\n\n    this.matches.push(url, name, callback);\n  }\n\n  generate(): MatchCallback {\n    let dslMatches = this.matches;\n\n    if (!this.explicitIndex) {\n      this.route('index', { path: '/' });\n    }\n","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@ember/routing/lib/dsl.ts#L130-L166","documentation":"In Ember's routing DSL, a custom serialize function may only be defined for routes inside an Engine (where it feeds addRouteForEngine). Defining serialize on a normal route map entry outside an engine is invalid because top-level routes serialize via the route's own serialize hook, so the DSL throws.","triggerScenarios":"Using dsl.route('path', { serialize: fn }) (via mount/branch APIs) where the dsl is not an engine context — i.e. options.addRouteForEngine is absent and serialize was supplied to push().","commonSituations":"Passing a serialize option when manually building a route map or in addons that manipulate the DSL; code written for ember-engines reused in a non-engine app.","solutions":["Remove the serialize option and define serialize as a method on the Route class instead","Only pass serialize for routes registered via addRouteForEngine inside engines","Move the route into an engine if engine-specific serialization is required"],"exampleFix":"// before\nthis.route('post', { serialize: mySerializer });\n// after\nthis.route('post');\n// and in the route:\n// export default class PostRoute extends Route { serialize(model) { return { id: model.id }; } }","handlingStrategy":"validation","validationCode":"if (serialize && !isEngineContext) { throw new Error('serialize option only allowed inside engines'); }","typeGuard":"function canPassSerialize(dslOptions) { return typeof dslOptions.addRouteForEngine === 'function'; }","tryCatchPattern":"try { buildRouteMap(dsl); } catch (e) { if (/route serializer .* outside an Engine/.test(e.message)) stripSerializeOptionsAndRebuild(); else throw e; }","preventionTips":["Put custom serialization on the Route class, not the DSL options","Use the serialize option only for engine-registered routes","Keep engine DSL helpers separate from app route maps"],"tags":["ember","routing","dsl","serialize","engines"],"backgroundTag":"invalid-route-serializer","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}