{"record":{"id":"f8303d142626b322","repo":"gchq/CyberChef","slug":"error-preparing-fonts-err","errorCode":null,"errorMessage":"Error preparing fonts. (${err})","messagePattern":"Error preparing fonts\\. \\((.+?)\\)","errorType":"exception","errorClass":"OperationError","httpStatus":null,"severity":"error","filePath":"src/core/operations/AddTextToImage.mjs","lineNumber":179,"sourceCode":"                fontsMap[\"Roboto Slab\"] = fonts[3];\n            });\n            // Make Webpack load the png font images\n            await Promise.all([\n                import(\n                    /* webpackMode: \"eager\" */ \"../../web/static/fonts/bmfonts/Roboto72White.png\"\n                ),\n                import(\n                    /* webpackMode: \"eager\" */ \"../../web/static/fonts/bmfonts/RobotoSlab72White.png\"\n                ),\n                import(\n                    /* webpackMode: \"eager\" */ \"../../web/static/fonts/bmfonts/RobotoMono72White.png\"\n                ),\n                import(\n                    /* webpackMode: \"eager\" */ \"../../web/static/fonts/bmfonts/RobotoBlack72White.png\"\n                ),\n            ]);\n        } catch (err) {\n            throw new OperationError(`Error preparing fonts. (${err})`);\n        }\n\n        let jimpFont;\n        try {\n            const font = fontsMap[fontFace];\n\n            // LoadFont needs an absolute url, so append the font name to self.docURL\n            jimpFont = await loadFont(self.docURL + \"/\" + font.default);\n\n            jimpFont.pages.forEach(function (page) {\n                if (page.bitmap) {\n                    // Adjust the RGB values of the image pages to change the font colour.\n                    const pageWidth = page.bitmap.width;\n                    const pageHeight = page.bitmap.height;\n                    for (let ix = 0; ix < pageWidth; ix++) {\n                        for (let iy = 0; iy < pageHeight; iy++) {\n                            const idx = (iy * pageWidth + ix) << 2;\n","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/gchq/CyberChef/blob/4290ea753912378913b1f3f54e0fc5720afeda5d/src/core/operations/AddTextToImage.mjs#L161-L197","documentation":"AddTextToImage dynamically imports four bundled bitmap-font assets (Roboto/RobotoSlab/RobotoMono/RobotoBlack .fnt + .png) via webpack eager imports. If any of these imports rejects, the operation throws 'Error preparing fonts.' This is a build/bundling/asset-loading problem, not a user-input problem.","triggerScenarios":"One or more of the eagerly-imported font modules fails to load: missing font files in the build output, a broken webpack chunk mapping, a CDN/path resolution failure, or an airgapped/offline environment where the chunk URL is unreachable.","commonSituations":"Custom build of CyberChef that excluded the font assets; deployment from a CDN where the .fnt/.png chunks 404; running in an environment where self.docURL / public path is misconfigured; webpack publicPath mismatch.","solutions":["Ensure the font assets under src/web/static/fonts/bmfonts/ are present and included in the build bundle.","Verify the deployment serves the generated font chunks at the configured publicPath.","Run the official build (npm run build) which bundles these eagerly-imported assets.","If airgapped, confirm the chunks are local (not fetched from a remote CDN)."],"exampleFix":"// before: custom build drops bmfonts → import() rejects → 'Error preparing fonts.'\n// after: keep src/web/static/fonts/bmfonts/* in the build inputs so the eager imports resolve","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await addTextToImage(input, ...);\n} catch (e) {\n  if (/Error preparing fonts/.test(e.message)) {\n    // build/deploy issue: ensure bmfonts assets are bundled and served\n    throw new Error('Font assets failed to load — check the build/deployment of static/fonts/bmfonts');\n  }\n  throw e;\n}","preventionTips":["Run the official build so the eager font imports are bundled.","Serve the generated font chunks at the configured publicPath.","On airgapped deployments, keep font assets local (no remote CDN)."],"tags":["image","jimp","fonts","build","bundling"],"backgroundTag":null,"analyzedSha":"4290ea753912378913b1f3f54e0fc5720afeda5d","analyzedAt":"2026-08-13T06:05:50.210Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}