remix-run/remix · error · Error
invalid origin ${JSON.stringify(origin)}
Error message
invalid origin ${JSON.stringify(origin)} What it means
The value must parse as a URL with a valid origin (scheme + host). If parseOrigin returns null the string is not a usable origin at all, so trusting it is impossible.
Source
Thrown at packages/cop-middleware/src/lib/cop.ts:186
}
let trimmedValue = value.trim()
return trimmedValue === '' ? null : trimmedValue
}
function validateTrustedOrigin(origin: string): string {
let trimmedOrigin = origin.trim()
if (trimmedOrigin === '') {
throw new Error('trusted origin must not be empty')
}
if (trimmedOrigin.endsWith('/')) {
throw new Error(`invalid origin ${JSON.stringify(origin)}: trailing slash is not allowed`)
}
let parsedOrigin = parseOrigin(trimmedOrigin)
if (parsedOrigin == null) {
throw new Error(`invalid origin ${JSON.stringify(origin)}`)
}
if (parsedOrigin.pathname !== '/' || parsedOrigin.search !== '' || parsedOrigin.hash !== '') {
throw new Error(
`invalid origin ${JSON.stringify(origin)}: path, query, and fragment are not allowed`,
)
}
return serializeOrigin(parsedOrigin)
}
function normalizeOrigin(origin: string): string | null {
let parsedOrigin = parseOrigin(origin)
return parsedOrigin == null ? null : serializeOrigin(parsedOrigin)
}
function parseOrigin(origin: string): URL | null {
try {View on GitHub (pinned to 9696913134)
Solutions
- Always include the scheme: 'https://example.com' or 'http://localhost:3000'
- For local dev use http://localhost:PORT explicitly
- Validate with `new URL(value)` in a config check before passing to the middleware
Example fix
// before
cop.addTrustedOrigin('api.example.com')
// after
cop.addTrustedOrigin('https://api.example.com') Defensive patterns
Strategy: type-guard
Validate before calling
function isOrigin(v: string) { try { return new URL(v).origin !== 'null' } catch { return false } }
if (!isOrigin(origin)) throw new Error('bad origin config') Type guard
function isValidOrigin(v: unknown): v is string {
if (typeof v !== 'string') return false
try { return new URL(v).origin !== 'null' } catch { return false }
} Prevention
- Always include the scheme
- Use http://localhost:3000 for local dev
- Lint config for missing protocols
When it happens
Trigger: addTrustedOrigin with values like 'example.com' (no scheme), 'localhost:3000', 'ftp://x', or random text.
Common situations: Omitting the protocol because browsers display URLs without it; using host:port strings from PORT env vars; typos in config files.
Related errors
- invalid origin ${JSON.stringify(origin)}: trailing slash is
- invalid origin ${JSON.stringify(origin)}: path, query, and f
- trusted origin must not be empty
- mounts keys must be URL pathnames without query strings, fra
- Resolved path escapes the allowed root: ${relativePath}
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/cacaf51b33543511.
Report an issue: GitHub.