strapi/strapi · critical
Invalid admin url config. Make sure the url is a non-empty s
Error message
Invalid admin url config. Make sure the url is a non-empty string.
What it means
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.
Source
Thrown at packages/core/core/src/configuration/urls.ts:38
}
if (serverUrl.startsWith('http')) {
try {
serverUrl = _.trim(new URL(serverConfig.url).toString(), '/');
} catch {
throw new Error(
'Invalid server url config. Make sure the url defined in server.js is valid.'
);
}
} else if (serverUrl !== '') {
serverUrl = `/${serverUrl}`;
}
// Defines adminUrl value
let adminUrl = _.get(adminConfig, 'url', '/admin');
adminUrl = _.trim(adminUrl, '/ ');
if (typeof adminUrl !== 'string') {
throw new Error('Invalid admin url config. Make sure the url is a non-empty string.');
}
if (adminUrl.startsWith('http')) {
try {
adminUrl = _.trim(new URL(adminUrl).toString(), '/');
} catch {
throw new Error('Invalid admin url config. Make sure the url defined in server.js is valid.');
}
} else {
adminUrl = `${serverUrl}/${adminUrl}`;
}
// Defines adminPath value
let adminPath = adminUrl;
if (
serverUrl.startsWith('http') &&
adminUrl.startsWith('http') &&
new URL(adminUrl).origin === new URL(serverUrl).origin &&
!forAdminBuildView on GitHub (pinned to 4a4101264d)
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.
Example fix
// before
module.exports = ({ env }) => ({
url: env.object('ADMIN_URL'), // resolves to a non-string object
});
// after
module.exports = ({ env }) => ({
url: env('ADMIN_URL', '/admin'),
}); Defensive patterns
Strategy: type-guard
Validate before calling
const adminUrl = config.admin?.url ?? '/admin';
if (typeof adminUrl !== 'string') {
throw new TypeError(`admin.url must be a string, got ${typeof adminUrl}`);
} Type guard
const isStringConfig = (v: unknown): v is string => typeof v === 'string';
Try / catch
try {
getConfigUrls(config);
} catch (e) {
if (e instanceof Error && /admin url config.*non-empty string/.test(e.message)) {
config.admin = { ...(config.admin ?? {}), url: '/admin' };
} else throw e;
} Prevention
- 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.
When it happens
Trigger: `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.
Common situations: 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.
Related errors
- Invalid admin url config. Make sure the url defined in serve
- Invalid server url config. Make sure the url defined in serv
- Missing auth.secret. Please set auth.secret in config/admin.
- Invalid server url config. Make sure the url is a string.
- ${declaration.resolve} couldn't be resolved
AI-assisted analysis of strapi/strapi@4a4101264d (2026-08-12).
Data as JSON: /api/errors/67436dfd94db024f.
Report an issue: GitHub.