remix-run/remix · error · AssetServerCompilationError

FILE_TRANSFORM_RESULT_INVALID

FILE_TRANSFORM_RESULT_INVALID

Error message

${formatFileTransformSubject(options.transformSubject)} must return a string, Uint8Array, or object for ${options.filePath}

What it means

A file transform (per-file or global) must return transformed content as a string, a Uint8Array, or a result object. After awaiting the transform, the compiler rejects any return value that is null or not an object when it expected the object form — i.e. the transform returned an unusable type such as a number, boolean, null, or undefined, failing with FILE_TRANSFORM_RESULT_INVALID.

Source

Thrown at packages/assets/src/lib/files/compiler.ts:710

): AssetFileTransformResult & { content: Uint8Array; extension: string } {
  if (typeof result === 'string') {
    return {
      content: new TextEncoder().encode(result),
      extension: options.currentExtension,
    }
  }

  if (result instanceof Uint8Array) {
    return {
      content: result,
      extension: options.currentExtension,
    }
  }

  if (result === null || typeof result !== 'object') {
    throw createAssetServerCompilationError(
      `${formatFileTransformSubject(options.transformSubject)} must return a string, Uint8Array, or object for ${options.filePath}`,
      { code: 'FILE_TRANSFORM_RESULT_INVALID' },
    )
  }

  if (
    !('content' in result) ||
    (typeof result.content !== 'string' && !(result.content instanceof Uint8Array))
  ) {
    throw createAssetServerCompilationError(
      `${formatFileTransformSubject(options.transformSubject)} must return a string or Uint8Array content value for ${options.filePath}`,
      { code: 'FILE_TRANSFORM_RESULT_INVALID' },
    )
  }

  let extension = options.currentExtension
  if ('extension' in result && result.extension !== undefined) {
    if (typeof result.extension !== 'string') {
      throw createAssetServerCompilationError(
        `${formatFileTransformSubject(options.transformSubject)} must return a string extension for ${options.filePath}`,

View on GitHub (pinned to 9696913134)

Solutions

  1. Return the content explicitly: a string, a Uint8Array, or `{ content, extension? }`
  2. For 'no change' paths, return the input content (or its bytes) rather than undefined/null
  3. Add a unit test asserting every branch of the transform returns a value

Example fix

// before
transform: (content, filePath) => {
  if (!filePath.endsWith('.md')) return // → undefined
  return minify(content)
}

// after
transform: (content, filePath) => {
  if (!filePath.endsWith('.md')) return content
  return minify(content)
}
Defensive patterns

Strategy: validation

Validate before calling

function validateTransformResult(result: unknown): string | Uint8Array | { content: string | Uint8Array; extension?: string } {
  if (typeof result === 'string' || result instanceof Uint8Array) return result
  if (result && typeof result === 'object' && 'content' in result) return result as any
  throw new TypeError('transform must return string, Uint8Array, or { content, extension? }')
}

// wrap your transform:
const safeTransform = (content, filePath) => validateTransformResult(myTransform(content, filePath))

Type guard

function isValidTransformResult(result: unknown): boolean {
  return (
    typeof result === 'string' ||
    result instanceof Uint8Array ||
    (!!result && typeof result === 'object')
  )
}

Prevention

When it happens

Trigger: A transform function that returns undefined (falls off the end), returns null, or returns a primitive like a number; also returning a Buffer-like or stream object that isn't a Uint8Array or the expected object shape.

Common situations: Writing a transform with an early-return path that forgets to return content; returning `undefined` to mean 'no change' (this API does not support that — return the original content instead); async transforms whose promise resolves to nothing because of a missed return.

Related errors


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