denoland/deno · error · TypeError

ERR_INVALID_MIME_SYNTAX

ERR_INVALID_MIME_SYNTAX

Error message

The MIME syntax for a type in "${str}" is invalid at ${invalidTypeIndex}

What it means

While parsing a MIME type string (util.ts:74), the portion before '/' (the type) must be a non-empty HTTP token: after skipping leading HTTP whitespace, if no '/' exists, the type is empty, or the type contains a non-token code point, ERR_INVALID_MIME_SYNTAX is thrown naming 'type' and the offending index.

Source

Thrown at ext/node/polyfills/internal/mime.ts:74

const SOLIDUS = "/";
const SEMICOLON = ";";

function parseTypeAndSubtype(
  str: string,
): [string, string, number] {
  // Skip only HTTP whitespace from start
  let position = safeStringSearch(str, END_BEGINNING_WHITESPACE);
  // read until '/'
  const typeEnd = StringPrototypeIndexOf(str, SOLIDUS, position);
  const trimmedType = typeEnd === -1
    ? StringPrototypeSlice(str, position)
    : StringPrototypeSlice(str, position, typeEnd);
  const invalidTypeIndex = safeStringSearch(
    trimmedType,
    NOT_HTTP_TOKEN_CODE_POINT,
  );
  if (trimmedType === "" || invalidTypeIndex !== -1 || typeEnd === -1) {
    throw new ERR_INVALID_MIME_SYNTAX("type", str, invalidTypeIndex);
  }
  // skip type and '/'
  position = typeEnd + 1;
  const type = toASCIILower(trimmedType);
  // read until ';'
  const subtypeEnd = StringPrototypeIndexOf(str, SEMICOLON, position);
  const rawSubtype = subtypeEnd === -1
    ? StringPrototypeSlice(str, position)
    : StringPrototypeSlice(str, position, subtypeEnd);
  position += rawSubtype.length;
  if (subtypeEnd !== -1) {
    // skip ';'
    position += 1;
  }
  const trimmedSubtype = StringPrototypeSlice(
    rawSubtype,
    0,
    safeStringSearch(rawSubtype, START_ENDING_WHITESPACE),

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Validate with a token regex before parsing: /^\s*[!#$%&'*+.^_|~A-Za-z0-9-]+\//.test(str).
  2. Trim and sanity-check user input: require exactly one '/', non-empty type and subtype.
  3. Fall back to a default MIME type (e.g. application/octet-stream) when input fails validation instead of forwarding it.

Example fix

// before
const m = new MIMEType(userInput); // userInput = 'plain' or 'te xt/plain'

// after
if (!/^\s*[!#$%&'*+.^_|~A-Za-z0-9-]+\/[!#$%&'*+.^_|~A-Za-z0-9-]+\s*(;|$)/.test(userInput ?? '')) {
  throw new TypeError('invalid MIME type');
}
const m = new MIMEType(userInput);
Defensive patterns

Strategy: validation

Validate before calling

const MIME_RE = /^\s*[!#$%&'*+.^_|~A-Za-z0-9-]+\/[!#$%&'*+.^_|~A-Za-z0-9-]+\s*(;|$)/;
if (!MIME_RE.test(String(input ?? ''))) throw new TypeError('invalid MIME type string');

Type guard

function looksLikeMimeType(s: string): boolean {
  return /^[!#$%&'*+.^_|~A-Za-z0-9-]+\/[!#$%&'*+.^_|~A-Za-z0-9-]+$/.test(s.trim().split(';')[0]);
}

Try / catch

try { new MIMEType(input); } catch (e) { if (e.code === 'ERR_INVALID_MIME_SYNTAX') { return fallbackType; } throw e; }

Prevention

When it happens

Trigger: Constructing MIMEType (or parsing via MIMEType.parse / node:mime polyfill used by headers such as Content-Type parsing paths) with strings like 'plain', '/json', 'te xt/plain', 'text/plain', or leading junk — the token scan NOT_HTTP_TOKEN_CODE_POINT locates the first illegal character.

Common situations: Forwarding user-supplied Content-Type/Accept values into a MIME API without validation; strings built with template literals that include a stray space or unicode char; empty type after whitespace trimming (' /plain'); data read from config with missing values yielding ''.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/9ebaed796b0ee933. Report an issue: GitHub.