angular/angular-cli · error
Failed to decode "${path}" as ${encoding} text.
Error message
Failed to decode "${path}" as ${encoding} text. What it means
UpdateRecorderBase's constructor decodes the file buffer with a fatal TextDecoder; if the bytes are not valid text for the chosen encoding (e.g. UTF-8), it throws this Error with the decoding TypeError as cause. It protects the recorder from building text edits over undecodable content.
Source
Thrown at packages/angular_devkit/schematics/src/tree/recorder.ts:35
}
}
export class UpdateRecorderBase implements UpdateRecorder {
protected _path: string;
protected content: MagicString;
constructor(
private readonly data: Uint8Array,
path: string,
encoding = 'utf-8',
private readonly bom = false,
) {
let text;
try {
text = new TextDecoder(encoding, { fatal: true, ignoreBOM: false }).decode(data);
} catch (e) {
if (e instanceof TypeError) {
throw new Error(`Failed to decode "${path}" as ${encoding} text.`, { cause: e });
}
throw e;
}
this._path = path;
this.content = new MagicString(text);
}
static createFromFileEntry(entry: FileEntry): UpdateRecorderBase {
const c0 = entry.content.byteLength > 0 && entry.content.readUInt8(0);
const c1 = entry.content.byteLength > 1 && entry.content.readUInt8(1);
const c2 = entry.content.byteLength > 2 && entry.content.readUInt8(2);
// Check if we're BOM.
if (c0 == 0xef && c1 == 0xbb && c2 == 0xbf) {
return new UpdateRecorderBase(entry.content, entry.path, 'utf-8', true);
} else if (c0 === 0xff && c1 == 0xfe) {View on GitHub (pinned to bb72145f9a)
Solutions
- Skip binary or undecodable files — check extension/content or catch this error and fall back to tree.overwrite with the original buffer.
- Verify the file is valid UTF-8 (or the expected encoding) before beginning an update.
- Explicitly pass the correct encoding when constructing the recorder instead of relying on defaults.
Example fix
// before
const recorder = tree.beginUpdate('/assets/logo.png');
// after
try {
const recorder = tree.beginUpdate('/assets/logo.png');
} catch (e) {
if (/Failed to decode/.test(String(e))) {
return; // skip binary file
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
function isDecodable(buf: Buffer, encoding = 'utf-8'): boolean {
try { new TextDecoder(encoding, { fatal: true }).decode(buf); return true; }
catch { return false; } Try / catch
try {
const recorder = tree.beginUpdate(path);
} catch (e) {
if (/^Failed to decode/.test(String(e))) {
return; // skip binary/undecodable file
}
throw e;
} Prevention
- Filter out binary extensions (.png, .ico, .woff) before text edits
- Pre-validate buffers with a fatal TextDecoder
- Specify the expected encoding explicitly when constructing recorders
- Investigate e.cause TypeError details for encoding mismatches
When it happens
Trigger: Calling tree.beginUpdate(path) where the file contains bytes invalid for the supplied encoding (binary files, wrong-charset files, corrupted content); passing a bad encoding string to a recorder constructor.
Common situations: Running codemods/schematics over binary assets (images, fonts, .ico), files saved with unexpected encodings (e.g. UTF-16), or locking/checkout artifacts; also editing files with BOM/encoding mismatches.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to decode "${path}" as UTF-8 text.
- Index ${index} outside of range [0, ${this.content.original.
- Content at path "${this.path}" has changed between the start
- schematicName cannot be undefined.
- The "not" keyword is not supported in JSON Schema.
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/727ba3f39eacbbfd.
Report an issue: GitHub.