{"record":{"id":"68dfc4c633ab8208","repo":"siyuan-note/siyuan","slug":"displayname-default-is-required","errorCode":null,"errorMessage":"displayName.default is required","messagePattern":"displayName\\.default is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/boot_appearance.go","lineNumber":679,"sourceCode":"\tfor _, part := range strings.Split(relative, string(os.PathSeparator)) {\n\t\tif part == \".\" || part == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tcurrent = filepath.Join(current, part)\n\t\tinfo, lstatErr := os.Lstat(current)\n\t\tif lstatErr != nil {\n\t\t\treturn lstatErr\n\t\t}\n\t\tif info.Mode()&os.ModeSymlink != 0 {\n\t\t\treturn ErrBootAppearanceAssetForbidden\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc validateBootAppearanceDisplayName(displayName map[string]string) error {\n\tif strings.TrimSpace(displayName[\"default\"]) == \"\" {\n\t\treturn errors.New(\"displayName.default is required\")\n\t}\n\tfor lang, value := range displayName {\n\t\tif strings.TrimSpace(lang) == \"\" || strings.TrimSpace(value) == \"\" || len(lang) > 32 || len(value) > 128 ||\n\t\t\tstrings.ContainsAny(value, \"\\x00\\r\\n\") {\n\t\t\treturn errors.New(\"invalid display name\")\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc normalizeBootAppearanceFrontends(manifestFrontends, pluginFrontends []string) ([]string, error) {\n\tcandidates := manifestFrontends\n\tif len(candidates) == 0 {\n\t\tcandidates = pluginFrontends\n\t}\n\tfrontends := []string{}\n\tseen := map[string]bool{}\n\tfor _, frontend := range candidates {","sourceCodeStart":661,"sourceCodeEnd":697,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/boot_appearance.go#L661-L697","documentation":"Thrown by validateBootAppearanceDisplayName when the manifest's displayName map has no non-blank \"default\" entry. The default name is mandatory so the UI can always show something regardless of locale. Loading the package is rejected.","triggerScenarios":"A manifest with displayName containing only language-specific keys (e.g. only \"zh_CN\") or an empty/whitespace \"default\" value, read during loadBootAppearance.","commonSituations":"Authors localizing every string but forgetting the required \"default\" key, or leaving \"default\": \"\" as a placeholder.","solutions":["Add \"default\" to displayName with a non-empty name in the manifest.","Trim whitespace: a default of only spaces also fails the check.","Keep localized entries in addition to, not instead of, \"default\"."],"exampleFix":"// before\n\"displayName\": {\"zh_CN\": \"启动画面\"}\n// after\n\"displayName\": {\"default\": \"Boot Splash\", \"zh_CN\": \"启动画面\"}","handlingStrategy":"validation","validationCode":"function hasDefaultName(m) { return m.displayName && typeof m.displayName.default === \"string\" && m.displayName.default.trim() !== \"\"; }","typeGuard":null,"tryCatchPattern":"try { await installBootAppearance(pkg); } catch (e) { if (String(e).includes(\"displayName.default is required\")) { /* add default name to manifest */ } else throw e; }","preventionTips":["Always include displayName.default first, then localize","Add a manifest linter step in packaging scripts","Never leave placeholder empty strings"],"tags":["validation","manifest","required-field"],"backgroundTag":"missing-required-config-field","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}