remix-run/remix · error · TypeError
hmr must create a channel with a string url
Error message
hmr must create a channel with a string url
What it means
`remix version` prints `context.remixVersion`, which is injected into the CLI context at build/publish time. When it's null/undefined — typically a dev checkout or a broken/incomplete packaging — the command can't print a meaningful version and throws `RMX_REMIX_VERSION_UNAVAILABLE`, with the surrounding catch writing the error to stderr.
Source
Thrown at packages/assets/src/lib/asset-server.ts:1124
if (channel === undefined) return null
validateBrowserHmrChannel(channel)
if (isClosed()) {
channel.close()
return null
}
setUnsubscribe(channel.onFileEvents(handleFileEvents))
return channel
})
}
function validateBrowserHmrChannel(channel: unknown): asserts channel is BrowserHmrChannel {
if (channel === null || typeof channel !== 'object') {
throw new TypeError('hmr must create an object')
}
if (!('url' in channel) || typeof channel.url !== 'string') {
throw new TypeError('hmr must create a channel with a string url')
}
if (!('close' in channel) || typeof channel.close !== 'function') {
throw new TypeError('hmr must create a channel with a close function')
}
if (!('onFileEvents' in channel) || typeof channel.onFileEvents !== 'function') {
throw new TypeError('hmr must create a channel with an onFileEvents function')
}
if (!('updateWatchedFiles' in channel) || typeof channel.updateWatchedFiles !== 'function') {
throw new TypeError('hmr must create a channel with an updateWatchedFiles function')
}
}
function normalizeBasePath(basePath: string): string {
if (typeof basePath !== 'string') {
throw new TypeError('basePath must be a string')
}
return normalizePathname(basePath || '/').replace(/\/+$/, '') || '/'View on GitHub (pinned to 9696913134)
Solutions
- Use a published CLI from npm: `npx remix version`
- If developing the CLI, run the build/version-injection step so `remixVersion` is populated
- Reinstall the CLI package in case the install is corrupted
Defensive patterns
Strategy: fallback
Validate before calling
// Read the version from the installed package instead of the CLI context
let version = JSON.parse(fs.readFileSync('node_modules/remix/package.json','utf8')).version;
console.log(version); Type guard
function hasVersion(ctx: { remixVersion: string | null }): boolean {
return ctx.remixVersion != null;
} Try / catch
Catch around `remix version`; on failure fall back to reading node_modules/remix/package.json for the version string.
Prevention
- Use published npm CLIs for version checks
- Avoid relying on dev-checkout CLIs in CI
- Reinstall the CLI if version reporting breaks
When it happens
Trigger: Invoking `remix version` when the running CLI's context lacks `remixVersion` (null or undefined), e.g. running from source without the version-injection build step or a corrupted install.
Common situations: Running the CLI from a repo checkout; packaging pipelines that skip version injection; corrupted node_modules installs.
Related errors
- throw new AssertionError(options)
- ${matcherName} requires a mock function with a .mock.calls p
- throw new AssertionError({ message, actual, expected, operat
- expect(received).toThrow() requires a function (got ${typeof
- expected promise to resolve, but it rejected with: ${stringi
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/da836804a8190648.
Report an issue: GitHub.