remix-run/remix · error · TypeError

Expected a file path or file:// URL, received "${filePath}"

Error message

Expected a file path or file:// URL, received "${filePath}"

What it means

The style compiler accepts only local file paths (resolved against rootDir) or file:// URLs for style inputs. Other URL schemes such as http:// or https:// throw, since the compiler must read styles from disk.

Source

Thrown at packages/assets/src/lib/styles/compiler.ts:217

        path,
        timestamp,
      }))
    },

    invalidateFileEvent(filePath, event) {
      let normalizedFilePath = normalizeFilePath(filePath)
      if (isWatchIgnored(normalizedFilePath)) return
      styleStore.invalidateForFileEvent(normalizedFilePath, event)
    },
  }

  function resolveInputFilePath(filePath: string): string {
    if (filePath.startsWith('file://')) {
      return normalizeFilePath(fileURLToPath(new URL(filePath)))
    }

    if (filePath.includes('://')) {
      throw new TypeError(`Expected a file path or file:// URL, received "${filePath}"`)
    }

    return resolveFilePath(resolvedOptions.rootDir, filePath)
  }

  async function getOrCreateResolvedStyles(records: StyleRecord[]): Promise<ResolvedStyle[]> {
    return mapWithConcurrency(records, preloadConcurrency, (record) =>
      getOrCreateResolvedStyle(record),
    )
  }

  async function getOrCreateResolvedStyle(record: StyleRecord): Promise<ResolvedStyle> {
    if (record.resolved && styleStore.isResolvedFresh(record)) return record.resolved

    let cacheKey = getRecordCacheKey(record)
    let existing = resolveInFlightByCacheKey.get(cacheKey)
    if (existing) return existing

View on GitHub (pinned to 9696913134)

Solutions

  1. Download the stylesheet locally and pass a relative path like 'styles/theme.css'
  2. Use file:/// URLs for absolute local paths
  3. Vendor third-party CSS into the project instead of remote references

Example fix

// before
stylePath: 'https://cdn.example.com/theme.css'
// after
stylePath: 'styles/theme.css'
Defensive patterns

Strategy: validation

Validate before calling

function isLocal(p: string) { return !p.includes('://') || p.startsWith('file://') }
if (!styles.every(isLocal)) throw new Error('remote style paths not supported')

Type guard

function isLocalFilePath(p: string): boolean {
  return p.startsWith('file://') || !p.includes('://')
}

Prevention

When it happens

Trigger: Passing 'https://example.com/theme.css' as a style path to the styles compiler (resolvedStyle/getPreloadLayers).

Common situations: Referencing CDN-hosted CSS in config meant for local files; copying URLs from link tags in HTML into compiler options; importing styles by URL in environments that support it (Vite-style) but not here.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/3fcd9fc974f115ef. Report an issue: GitHub.