gchq/CyberChef · error · OperationError

Invalid file type

Error message

Invalid file type

What it means

Play Media's present() re-detects the file type with detectFileType(data) and requires types[0].mime to start with 'audio' or 'video' before building the <audio>/<video> element. This is a second guard after run() already validated with isType; it can fire when detection returns a non-media type first (detectFileType returns an ordered list and present() only inspects index 0) or when the data passed to present differs from what run validated.

Source

Thrown at src/core/operations/PlayMedia.mjs:89

        }

        return input;
    }

    /**
     * Displays an audio or video element that may be able to play the media
     * file.
     *
     * @param {byteArray} data Data containing an audio or video file.
     * @returns {string} Markup to display a media player.
     */
    async present(data) {
        if (!data.length) return "";

        const types = detectFileType(data);
        const matches = /^audio|video/.exec(types[0].mime);
        if (!matches) {
            throw new OperationError("Invalid file type");
        }
        const dataURI = `data:${types[0].mime};base64,${toBase64(data)}`;
        const element = matches[0];

        let html = `<${element} src='${dataURI}' type='${types[0].mime}' controls>`;
        html += "<p>Unsupported media type.</p>";
        html += `</${element}>`;
        return html;
    }
}

export default PlayMedia;

View on GitHub (pinned to 4290ea7539)

Solutions

  1. Ensure the data reaching present() is the same media bytes validated by run().
  2. If the file has an ambiguous signature, re-encode it to a clean, unambiguous container.
  3. Confirm the file is genuinely audio/video and not mis-detected due to truncation.
  4. Treat both Play Media errors identically: the bytes are not recognised media.
Defensive patterns

Strategy: validation

Validate before calling

import { detectFileType } from "../lib/FileType.mjs";
const types = detectFileType(data);
if (!types.length || !/^audio|video/.test(types[0].mime)) {
  throw new Error("Top detected type is not audio/video");
}

Type guard

function topTypeIsMedia(data) {
  const types = detectFileType(data);
  return types.length > 0 && /^audio|video/.test(types[0].mime);
}

Try / catch

try {
  return await playMedia.present(data);
} catch (e) {
  if (e.message === "Invalid file type") {
    // detection disagrees with run(); re-encode to an unambiguous container
  }
  throw e;
}

Prevention

When it happens

Trigger: detectFileType returns a list whose first entry is a non-media type even though isType earlier matched an audio/video type deeper in the list; present() is called with empty/changed data; a file that triggers ambiguous signatures where the top match is not media.

Common situations: A file with a magic sequence shared by a non-media format that sorts first in detection; chaining ops that alter the byte array between run and present; very short or ambiguous inputs.

Related errors


AI-assisted analysis of gchq/CyberChef@4290ea7539 (2026-08-13). Data as JSON: /api/errors/dc3c8262ceb383bb. Report an issue: GitHub.