siyuan-note/siyuan · error
invalid video poster: %w
Error message
invalid video poster: %w
What it means
A video layer's poster must itself pass validateBootAppearanceResource with expectedType "image": relative safe path, existing regular file, .png/.jpg/.jpeg/.webp extension, image size cap, and sniffed content must really be an image. Failures are wrapped as "invalid video poster".
Source
Thrown at kernel/model/boot_appearance.go:473
if layer == nil || !isValidBootAppearanceID(layer.ID) || layerIDs[layer.ID] {
err = errors.New("invalid or duplicate layer ID")
return nil, err
}
layerIDs[layer.ID] = true
if layer.Type != "image" && layer.Type != "video" {
err = fmt.Errorf("unsupported layer type [%s]", layer.Type)
return nil, err
}
if _, _, err = validateBootAppearanceResource(pluginDir, appearanceDir, layer.Src, layer.Type); err != nil {
return nil, fmt.Errorf("invalid layer source: %w", err)
}
if layer.Type == "video" {
if layer.Poster == "" {
err = errors.New("video poster is required")
return nil, err
}
if _, _, err = validateBootAppearanceResource(pluginDir, appearanceDir, layer.Poster, "image"); err != nil {
return nil, fmt.Errorf("invalid video poster: %w", err)
}
} else if layer.Poster != "" {
err = errors.New("image layer cannot declare a poster")
return nil, err
}
fit := layer.Fit
if fit == "" {
fit = "cover"
}
if !isValidBootAppearanceFit(fit) {
err = fmt.Errorf("invalid layer fit [%s]", fit)
return nil, err
}
position := layer.Position
if position == "" {
position = "center"
}
if !isValidBootAppearancePosition(position) {View on GitHub (pinned to 8641553a1f)
Solutions
- Ensure the poster file exists in the appearance directory and the path is a relative '/'-separated path
- Use .png, .jpg, .jpeg, or .webp and confirm the file really is that image format (convert GIFs to WebP/PNG)
- Compress the poster under maxBootAppearanceImageSize
- Remove symlinks and place the real image file in the package
Example fix
// before
{"id": "anim", "type": "video", "src": "anim.mp4", "poster": "anim.gif"}
// after
{"id": "anim", "type": "video", "src": "anim.mp4", "poster": "anim.webp"} // real WebP file present Defensive patterns
Strategy: validation
Validate before calling
manifest.layers?.forEach(l => {
if (l.type !== "video" || !l.poster) return;
if (!/\.(png|jpe?g|webp)$/i.test(l.poster)) throw new Error(`poster ${l.poster} must be png/jpg/webp`);
const p = join(appearanceDir, l.poster);
if (!existsSync(p)) throw new Error(`poster missing: ${l.poster}`);
}); Prevention
- Convert posters to PNG/JPEG/WebP (never GIF) and verify the format with an image tool
- Ship the poster file with the plugin; do not reference files outside the appearance dir
- Keep posters under the image size cap
- Verify the poster renders (e.g. open in browser) before publishing
When it happens
Trigger: GetBootAppearances/getBootAppearanceByID loading a manifest where a video layer's poster points to a missing file, a non-image extension (e.g. .mp4, .gif), a traversal/symlink path, or a file whose bytes are not actually a PNG/JPEG/WebP image.
Common situations: Poster GIF not accepted (rename/convert to webp/png); poster.png forgotten when copying the appearance folder to another machine; poster extension renamed from .jpg to .png without converting; poster file larger than the image size cap.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- video poster is required
- Plugin ${pluginLabel} returned an invalid action
- Plugin ${pluginLabel} returned invalid input: ${targetValida
- invalid custom emoji image
- unsupported custom emoji image format
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/ad139e6b3bd454e2.
Report an issue: GitHub.