{"record":{"id":"67436dfd94db024f","repo":"strapi/strapi","slug":"invalid-admin-url-config-make-sure-the-url-is-a-n","errorCode":null,"errorMessage":"Invalid admin url config. Make sure the url is a non-empty string.","messagePattern":"Invalid admin url config\\. Make sure the url is a non-empty string\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/core/core/src/configuration/urls.ts","lineNumber":38,"sourceCode":"  }\n\n  if (serverUrl.startsWith('http')) {\n    try {\n      serverUrl = _.trim(new URL(serverConfig.url).toString(), '/');\n    } catch {\n      throw new Error(\n        'Invalid server url config. Make sure the url defined in server.js is valid.'\n      );\n    }\n  } else if (serverUrl !== '') {\n    serverUrl = `/${serverUrl}`;\n  }\n\n  // Defines adminUrl value\n  let adminUrl = _.get(adminConfig, 'url', '/admin');\n  adminUrl = _.trim(adminUrl, '/ ');\n  if (typeof adminUrl !== 'string') {\n    throw new Error('Invalid admin url config. Make sure the url is a non-empty string.');\n  }\n  if (adminUrl.startsWith('http')) {\n    try {\n      adminUrl = _.trim(new URL(adminUrl).toString(), '/');\n    } catch {\n      throw new Error('Invalid admin url config. Make sure the url defined in server.js is valid.');\n    }\n  } else {\n    adminUrl = `${serverUrl}/${adminUrl}`;\n  }\n\n  // Defines adminPath value\n  let adminPath = adminUrl;\n  if (\n    serverUrl.startsWith('http') &&\n    adminUrl.startsWith('http') &&\n    new URL(adminUrl).origin === new URL(serverUrl).origin &&\n    !forAdminBuild","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/strapi/strapi/blob/4a4101264d7098754df36e85fa629fd2f2349d8c/packages/core/core/src/configuration/urls.ts#L20-L56","documentation":"Defensive guard in getConfigUrls() that throws when `admin.url`, after lodash `_.trim`, is not a string. In practice lodash `_.trim` always returns a string (coercing numbers/objects/null), so this branch is effectively unreachable through normal config files; it exists to harden against exotic non-stringable inputs (e.g. a Symbol, which would make _.trim itself throw before this check). The message names admin config and is the companion to the server-url string check.","triggerScenarios":"`config.admin.url` is set to a value whose _.trim result is not a string. Because _.trim coerces, the realistic trigger is an upstream code path that injects a non-coercible value, or a custom config loader returning a Symbol/odd object whose toString throws. Through normal env/file config this is not expected to fire.","commonSituations":"Programmatically building the config object and assigning admin.url to a Symbol, BigInt, or an object with a throwing toString; a plugin or test harness mutating `strapi.config.set('admin.url', someNonString)` before getConfigUrls runs.","solutions":["Ensure `admin.url` is a literal string in config/admin.js (e.g. `url: '/admin'` or an absolute URL).","If you set admin.url dynamically, coerce it: `url: String(value)` before it reaches Strapi's config.","Avoid passing Symbol/BigInt/object-with-throwing-toString values through config.","If hitting this from a plugin, read the value via `strapi.config.get('admin.url', '/admin')` and assert it is a string."],"exampleFix":"// before\nmodule.exports = ({ env }) => ({\n  url: env.object('ADMIN_URL'), // resolves to a non-string object\n});\n\n// after\nmodule.exports = ({ env }) => ({\n  url: env('ADMIN_URL', '/admin'),\n});","handlingStrategy":"type-guard","validationCode":"const adminUrl = config.admin?.url ?? '/admin';\nif (typeof adminUrl !== 'string') {\n  throw new TypeError(`admin.url must be a string, got ${typeof adminUrl}`);\n}","typeGuard":"const isStringConfig = (v: unknown): v is string => typeof v === 'string';","tryCatchPattern":"try {\n  getConfigUrls(config);\n} catch (e) {\n  if (e instanceof Error && /admin url config.*non-empty string/.test(e.message)) {\n    config.admin = { ...(config.admin ?? {}), url: '/admin' };\n  } else throw e;\n}","preventionTips":["Always declare admin.url as a string literal in config.","Use env() (not env.object/env.array) for URL config so types stay string.","Add a config schema (config/schema) to reject non-string admin.url at load time."],"tags":["config","url","startup","admin-config","defensive-guard"],"backgroundTag":null,"analyzedSha":"4a4101264d7098754df36e85fa629fd2f2349d8c","analyzedAt":"2026-08-12T12:47:50.760Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}