{"record":{"id":"3f7a84dcd7f197f1","repo":"d2lang/d2","slug":"failed-to-read-font-at-s-v","errorCode":null,"errorMessage":"failed to read font at %s: %v","messagePattern":"failed to read font at (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2cli/main.go","lineNumber":1323,"sourceCode":"\n\treturn nil\n}\n\nfunc initPlaywright() error {\n\tpw, err := png.InitPlaywrightWithPrompt()\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn pw.Cleanup()\n}\n\nfunc loadFont(ms *xmain.State, path string) ([]byte, error) {\n\tif filepath.Ext(path) != \".ttf\" {\n\t\treturn nil, fmt.Errorf(\"expected .ttf file but %s has extension %s\", path, filepath.Ext(path))\n\t}\n\tttf, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read font at %s: %v\", path, err)\n\t}\n\tms.Log.Info.Printf(\"font %s loaded\", filepath.Base(path))\n\treturn ttf, nil\n}\n\nfunc loadFonts(ms *xmain.State, pathToRegular, pathToItalic, pathToBold, pathToSemibold, pathToMono, pathToMonoBold, pathToMonoItalic, pathToMonoSemibold string) (*d2fonts.FontFamily, *d2fonts.FontFamily, error) {\n\tif pathToRegular == \"\" && pathToItalic == \"\" && pathToBold == \"\" && pathToSemibold == \"\" &&\n\t\tpathToMono == \"\" && pathToMonoBold == \"\" && pathToMonoItalic == \"\" && pathToMonoSemibold == \"\" {\n\t\treturn nil, nil, nil\n\t}\n\n\tvar regularTTF []byte\n\tvar italicTTF []byte\n\tvar boldTTF []byte\n\tvar semiboldTTF []byte\n\tvar monoTTF []byte\n\tvar monoBoldTTF []byte\n\tvar monoItalicTTF []byte","sourceCodeStart":1305,"sourceCodeEnd":1341,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2cli/main.go#L1305-L1341","documentation":"After the extension check passes, loadFont reads the font file with os.ReadFile. If the file cannot be read — missing file, permission denied, path is a directory — the underlying OS error is wrapped and returned.","triggerScenarios":"loadFont called with a .ttf path that does not exist, points to a directory, or is not readable by the current user.","commonSituations":"Typo in the font path, font file deleted or moved after configuring flags, relative path resolved from a different working directory, or restricted file permissions on shared systems.","solutions":["Verify the path exists with `ls -l <path>` and correct any typo","Use an absolute path for the font file","Check file permissions (chmod/chown) so the running user can read it"],"exampleFix":"// before\nd2 --font-regular=./fonts/Inter.ttf sketch.d2   # run from wrong dir\n// after\nd2 --font-regular=/usr/share/fonts/Inter-Regular.ttf sketch.d2","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(fontPath); err != nil {\n\t// fail fast: path missing or inaccessible\n\tos.Exit(1)\n}","typeGuard":"func fontReadable(path string) bool {\n\tf, err := os.Open(path)\n\tif err != nil { return false }\n\tf.Close()\n\treturn true\n}","tryCatchPattern":"ttf, err := loadFont(ms, path)\nif err != nil {\n\tms.Log.Error.Print(err)\n\treturn fmt.Errorf(\"check font path %s exists and is readable\", path)\n}","preventionTips":["Verify font paths exist before running d2","Use absolute paths for fonts","Check permissions on shared/CI systems"],"tags":["cli","fonts","filesystem"],"backgroundTag":"file-not-found","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}