{"record":{"id":"39374db8c4cc7c72","repo":"angular/angular","slug":"http-origin-map-used-in-client","errorCode":"HTTP_ORIGIN_MAP_USED_IN_CLIENT","errorMessage":"Angular detected that the `HTTP_TRANSFER_CACHE_ORIGIN_MAP` token is configured and present in the client side code. Please ensure that this token is only provided in the server code of the application.","messagePattern":"Angular detected that the `HTTP_TRANSFER_CACHE_ORIGIN_MAP` token is configured and present in the client side code\\. Please ensure that this token is only provided in the server code of the application\\.","errorType":"error_code","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"packages/common/http/src/transfer_cache.ts","lineNumber":212,"sourceCode":" * @param transferState The transfer state to retrieve the cached response from.\n * @param originMap The origin map to map the request URL to the origin. (Not needed when `storeKey` is provided).\n * @param storeKey The key to use to store the cached response in the transfer state. (If not provided, it will be computed from the request and originMap).\n * @param skipUseCacheChecks Whether to skip the use cache checks. (Only disable when the checks have been performed beforehand).\n */\nexport function retrieveStateFromCache(\n  req: HttpRequest<unknown>,\n  options: CacheOptions,\n  transferState: TransferState,\n  originMap: Record<string, string> | null,\n  storeKey?: StateKey<TransferHttpResponse>,\n  skipUseCacheChecks = false,\n): HttpResponse<unknown> | null {\n  if (!skipUseCacheChecks && !canUseOrCacheRequest(req, options)) {\n    return null;\n  }\n\n  if (typeof ngServerMode !== 'undefined' && !ngServerMode && originMap) {\n    throw new RuntimeError(\n      RuntimeErrorCode.HTTP_ORIGIN_MAP_USED_IN_CLIENT,\n      ngDevMode &&\n        'Angular detected that the `HTTP_TRANSFER_CACHE_ORIGIN_MAP` token is configured and ' +\n          'present in the client side code. Please ensure that this token is only provided in the ' +\n          'server code of the application.',\n    );\n  }\n\n  if (!storeKey) {\n    const requestUrl =\n      typeof ngServerMode !== 'undefined' && ngServerMode && originMap\n        ? mapRequestOriginUrl(req.url, originMap)\n        : req.url;\n\n    storeKey = makeCacheKey(req, requestUrl);\n  }\n\n  const response = transferState.get(storeKey, null);","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/common/http/src/transfer_cache.ts#L194-L230","documentation":"Thrown by the transfer-cache code when HTTP_TRANSFER_CACHE_ORIGIN_MAP has a value while running in the browser (ngServerMode is false). The origin map exists solely to rewrite absolute API origins to internal ones during server-side rendering (so SSR fetches stay on the private network); shipping it to the client leaks internal topology and is meaningless there, so its presence in client-side DI is treated as a misconfiguration.","triggerScenarios":"Providing {provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP, useValue: {...}} in app.config.ts (shared by browser and server bootstraps) instead of the server-only config; putting it in a shared providers array imported by both main.ts and server.ts.","commonSituations":"Adding the origin map while enabling SSR transfer cache on an existing app where app.config.ts is shared; refactoring that moves providers between shared and server configs; a monorepo shared UI lib that registers HTTP providers.","solutions":["Move the HTTP_TRANSFER_CACHE_ORIGIN_MAP provider into the server-only configuration (app.config.server.ts / server providers array)","If configs are merged, gate it: isPlatformServer(platformId) ? {provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP, ...} : []","Keep withTransferCacheOptions()/withHttpTransferCache in the shared config — only the origin map must be server-side","Verify with a browser-only build that the token no longer appears in client DI"],"exampleFix":"// before — app.config.ts shared by browser and server\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideHttpClient(withHttpTransferCache(...)),\n    {provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP, useValue: {'https://api.example.com': 'http://internal:3000'}},\n  ],\n};\n\n// after — map lives only in the server config (app.config.server.ts)\nconst serverConfig: ApplicationConfig = {\n  providers: [\n    {provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP, useValue: {'https://api.example.com': 'http://internal:3000'}},\n  ],\n};","handlingStrategy":"validation","validationCode":"// build providers per platform\nexport function httpProviders(platformId: Object): Provider[] {\n  const shared = [provideHttpClient(withHttpTransferCache({includePostRequests: false}))];\n  return isPlatformServer(platformId)\n    ? [...shared, {provide: HTTP_TRANSFER_CACHE_ORIGIN_MAP, useValue: SERVER_ORIGIN_MAP}]\n    : shared;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep HTTP_TRANSFER_CACHE_ORIGIN_MAP exclusively in app.config.server.ts / server.ts providers","When merging shared + server configs, add a startup assertion: if (!ngServerMode && inject(HTTP_TRANSFER_CACHE_ORIGIN_MAP, {optional: true})) fail fast in CI","Review any shared providers array in a monorepo lib before adding HTTP transfer-cache tokens"],"tags":["http","ssr","transfer-cache","configuration"],"backgroundTag":"server-only-config-in-client","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}