siyuan-note/siyuan · error

video poster is required

Error message

video poster is required

What it means

Video layers must declare a poster image: if layer.Type is "video" and layer.Poster is empty, loadBootAppearance aborts. The poster is shown before the video loads/plays on the boot screen, so it is mandatory for video layers.

Source

Thrown at kernel/model/boot_appearance.go:469

	}

	layerIDs := map[string]bool{}
	for _, layer := range manifest.Layers {
		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

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Add a poster field pointing to a PNG/JPEG/WebP image in the appearance directory for every video layer
  2. Generate a poster by exporting a frame of the video (e.g. first frame) as poster.png
  3. Re-validate the manifest so the video layer reads like {"type":"video","src":"x.mp4","poster":"poster.png"}

Example fix

// before
{"id": "anim", "type": "video", "src": "anim.mp4"}
// after
{"id": "anim", "type": "video", "src": "anim.mp4", "poster": "anim-poster.png"}
Defensive patterns

Strategy: validation

Validate before calling

manifest.layers?.forEach(l => {
  if (l.type === "video" && (!l.poster || typeof l.poster !== "string")) {
    throw new Error(`video layer ${l.id} requires a poster`);
  }
});

Type guard

const hasPoster = (l: { type: string; poster?: string }): boolean =>
  l.type !== "video" || (typeof l.poster === "string" && l.poster.length > 0);

Prevention

When it happens

Trigger: GetBootAppearances/getBootAppearanceByID loading a manifest.json where a layer with "type": "video" omits the poster field or sets it to "".

Common situations: Author adds a video layer copied from an image-layer template that had no poster field; poster considered optional; a generator that only emits src for video layers.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/16b3fdbeb18019e9. Report an issue: GitHub.