QL-Win/QuickLook · error · InvalidDataException
DS_Store: unknown record type '{stype}'
Error message
DS_Store: unknown record type '{stype}' What it means
Thrown while parsing a macOS .DS_Store file: after skipping a 4-byte sid and reading a 4-byte ASCII type tag, the tag did not match any of the known record types (bool, type, long, shor, comp, dutc, blob, ustr). This is an InvalidDataException signalling that the parser encountered a structure it cannot decode. The QuickLook ArchiveViewer uses this to bail out on a malformed or unsupported .DS_Store embedded inside a ZIP/archive.
Source
Thrown at QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/DSStore/DSStoreExtractor.cs:245
public string ReadFileName()
{
uint length = ReadUint32();
byte[] buf = ReadBuf((int)(2 * length));
// skip sid (4 bytes) and read type tag (4 bytes)
Skip(4);
byte[] stypeBytes = ReadBuf(4);
string stype = Encoding.ASCII.GetString(stypeBytes);
int bytesToSkip = stype switch
{
"bool" => 1,
"type" or "long" or "shor" => 4,
"comp" or "dutc" => 8,
"blob" => (int)ReadUint32(),
"ustr" => (int)(2 * ReadUint32()),
_ => throw new InvalidDataException($"DS_Store: unknown record type '{stype}'")
};
Skip((uint)bytesToSkip);
// filename is encoded as UTF-16 big-endian
return Encoding.BigEndianUnicode.GetString(buf);
}
}
}
View on GitHub (pinned to cb5d9c429c)
Solutions
- Confirm the file is a genuine .DS_Store (magic 'Bud1\0' at offset 0) before invoking the extractor.
- If you control the parser, map the new tag to its documented size instead of throwing, or extend the switch with the missing case.
- Wrap the extraction in a try/catch for InvalidDataException and fall back to skipping the .DS_Store entry when previewing an archive.
- Re-download or re-create the archive if the .DS_Store is byte-corrupted.
Example fix
// before
_ => throw new InvalidDataException($"DS_Store: unknown record type '{stype}'")
// after: tolerate unknown tags by reading a length-prefixed value when present
_ => (int)ReadUint32() Defensive patterns
Strategy: validation
Validate before calling
// verify .DS_Store magic 'Bud1\0' (0x42756431 then 0x0000) before parsing using var fs = File.OpenRead(path); Span<byte> magic = stackalloc byte[8]; if (await fs.ReadAsync(magic) < 8) return false; return magic[0]=='B' && magic[1]=='u' && magic[2]=='d' && magic[3]=='1' && magic[4]==0 && magic[5]==0;
Type guard
static bool IsLikelyDsStore(byte[] head) => head.Length >= 8 && head[0]=='B' && head[1]=='u' && head[2]=='d' && head[3]=='1';
Try / catch
try { DSStoreExtractor.Extract(stream); }
catch (InvalidDataException) { /* skip this .DS_Store entry, continue archive preview */ } Prevention
- Only feed the extractor files that pass the 'Bud1' magic check.
- Treat .DS_Store parse failures as non-fatal when previewing archives.
- Extend the type-tag switch when adopting newer macOS .DS_Store formats.
When it happens
Trigger: ReadBuf(4) returns 4 bytes whose ASCII decoding is not one of {bool, type, long, shor, comp, dutc, blob, ustr}; the switch expression falls to its '_' arm. Happens when the .DS_Store stream is truncated, byte-shifted, or produced by a macOS version that emits a record type this parser does not know.
Common situations: Corrupted download of a macOS archive; a .DS_Store rewritten by a newer macOS release that introduced a new value type; a file that merely has a .DS_Store name but is not actually a Finder .DS_Store; partial extraction leaving the record header incomplete.
Related errors
- 1 BPP mask underrun parsing ICNS file
- DS_Store header too short
- DS_Store: wrong magic (expected 0x00000001)
- DS_Store: wrong magic (expected 'Bud1')
- DS_Store: root-block offset mismatch
AI-assisted analysis of QL-Win/QuickLook@cb5d9c429c (2026-08-13).
Data as JSON: /api/errors/70ef8df2d5326b99.
Report an issue: GitHub.