{"record":{"id":"54199b7ac1dce996","repo":"siyuan-note/siyuan","slug":"invalid-display-name","errorCode":null,"errorMessage":"invalid display name","messagePattern":"invalid display name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/boot_appearance.go","lineNumber":684,"sourceCode":"\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 {\n\t\tif frontend == \"all\" && len(manifestFrontends) == 0 {\n\t\t\tfor _, normalized := range []string{\"desktop\", \"mobile\"} {\n\t\t\t\tif !seen[normalized] {\n\t\t\t\t\tseen[normalized] = true\n\t\t\t\t\tfrontends = append(frontends, normalized)","sourceCodeStart":666,"sourceCodeEnd":702,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/boot_appearance.go#L666-L702","documentation":"Thrown by validateBootAppearanceDisplayName when any displayName entry violates the field constraints: empty/blank language key or value, language key longer than 32 bytes, value longer than 128 bytes, or value containing NUL/CR/LF. It enforces sane, single-line display names.","triggerScenarios":"A manifest displayName entry like \"\": \"Name\", \"en_US\": \"  \", an over-long name (>128 chars), or a name with embedded \"\\n\"; hit while loading the package.","commonSituations":"Pasting multi-line marketing text as the name, generating manifests programmatically with empty keys, or very long product names.","solutions":["Ensure every displayName key is a non-empty locale tag of at most 32 characters.","Ensure every value is non-blank, at most 128 characters, and contains no newlines/CR/NUL.","Collapse multi-line names into a single line and move descriptions elsewhere."],"exampleFix":"// before\n\"displayName\": {\"\": \"My Boot\\nSplash\"}\n// after\n\"displayName\": {\"default\": \"My Boot Splash\"}","handlingStrategy":"validation","validationCode":"function validDisplayNames(dn) { return Object.entries(dn || {}).every(([lang, v]) => lang.trim() !== \"\" && typeof v === \"string\" && v.trim() !== \"\" && lang.length <= 32 && v.length <= 128 && !/[\\u0000\\r\\n]/.test(v)); }","typeGuard":null,"tryCatchPattern":"try { await installBootAppearance(pkg); } catch (e) { if (String(e).includes(\"invalid display name\")) { /* fix offending displayName entry */ } else throw e; }","preventionTips":["Validate displayName against length and charset rules in packaging CI","Strip newlines from generated names","Keep locale keys under 32 chars"],"tags":["validation","manifest","display-name"],"backgroundTag":"schema-validation-failed","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"}