{"record":{"id":"9c665ca659bae381","repo":"siyuan-note/siyuan","slug":"invalid-layer-fit-s","errorCode":null,"errorMessage":"invalid layer fit [%s]","messagePattern":"invalid layer fit \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/boot_appearance.go","lineNumber":484,"sourceCode":"\t\t}\n\t\tif layer.Type == \"video\" {\n\t\t\tif layer.Poster == \"\" {\n\t\t\t\terr = errors.New(\"video poster is required\")\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif _, _, err = validateBootAppearanceResource(pluginDir, appearanceDir, layer.Poster, \"image\"); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid video poster: %w\", err)\n\t\t\t}\n\t\t} else if layer.Poster != \"\" {\n\t\t\terr = errors.New(\"image layer cannot declare a poster\")\n\t\t\treturn nil, err\n\t\t}\n\t\tfit := layer.Fit\n\t\tif fit == \"\" {\n\t\t\tfit = \"cover\"\n\t\t}\n\t\tif !isValidBootAppearanceFit(fit) {\n\t\t\terr = fmt.Errorf(\"invalid layer fit [%s]\", fit)\n\t\t\treturn nil, err\n\t\t}\n\t\tposition := layer.Position\n\t\tif position == \"\" {\n\t\t\tposition = \"center\"\n\t\t}\n\t\tif !isValidBootAppearancePosition(position) {\n\t\t\terr = fmt.Errorf(\"invalid layer position [%s]\", position)\n\t\t\treturn nil, err\n\t\t}\n\t\titem := &BootAppearanceLayer{\n\t\t\tID:       layer.ID,\n\t\t\tType:     layer.Type,\n\t\t\tSrc:      bootAppearanceAssetURL(pkg.Name, appearanceID, layer.Src),\n\t\t\tFit:      fit,\n\t\t\tPosition: position,\n\t\t}\n\t\tif layer.Poster != \"\" {","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/boot_appearance.go#L466-L502","documentation":"Thrown by loadBootAppearance when a boot appearance manifest declares a layer whose \"fit\" value is not one of the accepted CSS-like object-fit values. Empty fit values default to \"cover\" so this only fires for explicitly wrong strings. It aborts loading of the whole boot appearance package.","triggerScenarios":"Calling GetBootAppearances or getBootAppearanceByID while a manifest.json contains a layer with e.g. \"fit\": \"stretch\" or \"Fit\": \"Cover\" (case-sensitive, must be lowercase cover/contain/fill/none/scale-down).","commonSituations":"Hand-edited manifest files, copy-pasted CSS values like \"object-fit: cover\", wrong casing (\"Cover\"), or manifests written against an older/imagined spec.","solutions":["Open the boot appearance package's manifest and change the layer's fit to one of: cover, contain, fill, none, scale-down (lowercase).","Remove the fit field entirely to get the default \"cover\".","Validate the manifest with a quick check before shipping: allowed set is cover|contain|fill|none|scale-down."],"exampleFix":"// before\n\"fit\": \"Cover\"\n// after\n\"fit\": \"cover\"","handlingStrategy":"validation","validationCode":"function validLayerFit(fit) { return !fit || [\"cover\",\"contain\",\"fill\",\"none\",\"scale-down\"].includes(fit); }","typeGuard":"const isLayerFit = (v) => typeof v === \"string\" && [\"cover\",\"contain\",\"fill\",\"none\",\"scale-down\"].includes(v);","tryCatchPattern":"try { appearances = await getBootAppearances(); } catch (e) { if (String(e).includes(\"invalid layer fit\")) { /* fix manifest, skip package */ } else throw e; }","preventionTips":["Use a manifest schema/JSON Schema validator with an enum on fit before packaging","Always write fit values lowercase","Omit fit when the default cover is fine"],"tags":["validation","boot-appearance","manifest"],"backgroundTag":"invalid-enum-value","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"}