JuliusBrussee/caveman · error · Error
[extract-atlas] missing base64 const
Error message
[extract-atlas] missing base64 const ${name} What it means
`constB64` extracts base64 string constants (`const NAME = "...";`) from source text read by extract-atlas.mjs and decodes them to a Buffer. This error is thrown when the regex finds no match, meaning the expected base64 constant is missing or no longer a plain double-quoted string literal.
Solutions
- Restore the constant as a single-line double-quoted string: const NAME = "<base64>";
- Re-run the step that generates the embedded blob so the constant is regenerated in place
- If the data moved to a file, change extract-atlas.mjs to read the file instead of regexing source
- Check that the correct source text (not an empty or wrong file's contents) is passed to constB64
Example fix
// before const ATLAS_PNG = await loadAtlas(); // dynamic, regex can't match // after const ATLAS_PNG = "iVBORw0KGgo..."; // plain base64 literal
Defensive patterns
Strategy: validation
Validate before calling
function b64ConstPresent(src, name) {
return new RegExp(`const\\s+${name}\\s*=\\s*"([^"]+)"\\s*;`).test(src);
}
if (!b64ConstPresent(src, "ATLAS_PNG")) throw new Error("base64 blob constant missing"); Try / catch
try {
runAtlasExtract();
} catch (e) {
if (String(e.message).includes("missing base64 const")) {
console.error("Regenerate the embedded base64 constant before extracting the atlas");
} else throw e;
} Prevention
- Keep base64 blobs as single-line double-quoted string literals
- Run the blob generator before extract-atlas in the build order
- Disable formatters/minifiers for files carrying generated string constants
- Move large blobs to data files instead of inlining if constants keep churning
When it happens
Trigger: Source no longer contains `const ${name} = "<base64>";` — the constant was renamed, moved to another file, changed to a template literal/backticks, imported instead of declared, or split across lines.
Common situations: A formatter or minifier rewrote the string literal; the asset blob was moved into a separate .json/.bin file during a refactor; the constant was made `export const` with extra spacing that still matches but the value was emptied and replaced with dynamic generation.
Related errors
- [extract-atlas] missing numeric const
- envelope: decode wrapped key
- [extract-atlas] = , want
- is not canonical base64
- must be base64 or null
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/1cb3b7e5940a5bfb.
Report an issue: GitHub.
Appendix: source
Thrown at engine/pixel/internal/atlasgen/extract-atlas.mjs:37
const repoRoot = resolve(new URL('../../../../..', import.meta.url).pathname);
const outDir = join(repoRoot, 'public/engine/pixel/assets');
mkdirSync(outDir, { recursive: true });
function readSource(rel) {
return readFileSync(join(pxpipeRoot, rel), 'utf8');
}
function constNumber(src, name) {
const re = new RegExp(`export\\s+const\\s+${name}\\s*=\\s*(\\d+)\\s*;`);
const m = src.match(re);
if (!m) throw new Error(`[extract-atlas] missing numeric const ${name}`);
return Number(m[1]);
}
function constB64(src, name) {
const re = new RegExp(`const\\s+${name}\\s*=\\s*"([^"]+)"\\s*;`);
const m = src.match(re);
if (!m) throw new Error(`[extract-atlas] missing base64 const ${name}`);
return Buffer.from(m[1], 'base64');
}
function assertHeader(src, expected) {
for (const [name, want] of Object.entries(expected)) {
const got = constNumber(src, name);
if (got !== want) {
throw new Error(`[extract-atlas] ${name}=${got}, want ${want}`);
}
}
}
function writeBlob(name, bytes) {
const out = join(outDir, name);
writeFileSync(out, gzipSync(bytes, { level: 9 }));
console.log(`${basename(out)} raw=${bytes.length} gzip=${readFileSync(out).length}`);
}
View on GitHub (pinned to 3ee70a1026)