n8n-io/n8n · error · Error

Invalid file type

Error message

Invalid file type

What it means

Plain `Error('Invalid file type')` thrown at e2e.controller.ts:417 by the heap-snapshot download route when `req.params.filename` (after `path.basename`) does not end with `.heapsnapshot`. This controller is test-only — it hard-exits the process unless running under E2E (see top of file). The thrown `Error` is not a typed n8n error and will be serialized to a 500 by the generic response handler.

Source

Thrown at packages/cli/src/controllers/e2e.controller.ts:417

			sizeBytes: stats.size,
			sizeMB: Math.round(stats.size / 1024 / 1024),
		};
	}

	private heapSnapshotPaths = new Map<string, string>();

	/**
	 * Download a heap snapshot file as a stream.
	 * The response-helper pipes Readable streams directly to the response.
	 */
	@Get('/heap-snapshot/:filename', { skipAuth: true })
	downloadHeapSnapshot(req: Request) {
		const fs = require('node:fs') as typeof nodeFs;
		const path = require('node:path') as typeof nodePath;

		const filename = path.basename(req.params.filename);
		if (!filename.endsWith('.heapsnapshot')) {
			throw new Error('Invalid file type');
		}

		// Look up the full path stored during POST, or try cwd
		const filePath = this.heapSnapshotPaths.get(filename) ?? path.resolve(filename);
		if (!fs.existsSync(filePath)) {
			throw new Error(`Snapshot not found: ${filename} (tried ${filePath})`);
		}

		return fs.createReadStream(filePath);
	}

	// --- Per-spec backend V8 coverage (DEVP-370) -----------------------------
	// Lets the Playwright coverage fixture attribute this main process's V8
	// coverage to the spec that produced it, so backend source files land in the
	// E2E impact map (today the map is frontend-only). Test-only: the whole
	// controller hard-exits outside E2E (see top of file).
	//
	// Uses `Profiler.getBestEffortCoverage` (NON-draining) + a server-side

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Pass a filename ending in `.heapsnapshot` produced by the POST heap-snapshot route.
  2. Use the filename exactly as stored in `heapSnapshotPaths` (set during POST).
  3. If writing a test fixture, assert the extension before constructing the URL.

Example fix

// before
GET /e2e/heap-snapshot/dump.json
// 500 Invalid file type

// after
GET /e2e/heap-snapshot/dump.heapsnapshot
Defensive patterns

Strategy: validation

Validate before calling

function assertHeapFile(name: string) {
  if (!name.endsWith('.heapsnapshot')) throw new TypeError('Invalid file type');
}

Type guard

const isHeapSnapshotFile = (f: unknown): f is string =>
  typeof f === 'string' && f.endsWith('.heapsnapshot');

Prevention

When it happens

Trigger: In E2E/test mode only: hitting `GET /e2e/heap-snapshot/<filename>` with a filename whose extension isn't `.heapsnapshot` — e.g. `.json`, `.txt`, or no extension. Cannot occur in production because the controller aborts startup outside E2E.

Common situations: Playwright fixtures building the wrong URL; manual curl during local E2E runs; typos in fixture file paths.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/0c680fb811022d49. Report an issue: GitHub.