siyuan-note/siyuan · error

no supported frontend

Error message

no supported frontend

What it means

Thrown by normalizeBootAppearanceFrontends when after normalization no usable frontend remains: declared frontends were all invalid, or plugin frontends filtered everything out while manifestFrontends was empty. The default [desktop, mobile] is only applied when both input lists are completely empty.

Source

Thrown at kernel/model/boot_appearance.go:728

			normalized = "desktop"
		case "mobile":
			normalized = "mobile"
		default:
			if len(manifestFrontends) > 0 {
				return nil, fmt.Errorf("unsupported frontend [%s]", frontend)
			}
			continue
		}
		if !seen[normalized] {
			seen[normalized] = true
			frontends = append(frontends, normalized)
		}
	}
	if len(frontends) == 0 && len(manifestFrontends) == 0 && len(pluginFrontends) == 0 {
		frontends = append(frontends, "desktop", "mobile")
	}
	if len(frontends) == 0 {
		return nil, errors.New("no supported frontend")
	}
	return frontends, nil
}

func validateOptionalBootAppearanceColor(color string) error {
	if color != "" && !bootAppearanceColorPattern.MatchString(color) {
		return fmt.Errorf("invalid color [%s]", color)
	}
	return nil
}

func isValidBootAppearanceID(id string) bool {
	return len(id) <= 64 && bootAppearanceIDPattern.MatchString(id)
}

func isSafeBootAppearanceRelativePath(relativePath string) bool {
	if relativePath == "" || len(relativePath) > maxBootAppearancePathLength || strings.Contains(relativePath, "\\") ||
		strings.ContainsAny(relativePath, `<>:"|?*`) || strings.HasPrefix(relativePath, "/") ||

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Set manifest frontends to ["desktop"], ["mobile"], or ["desktop","mobile"].
  2. If using plugin frontends, ensure they include at least desktop or mobile.
  3. Remove the conflicting plugin frontend declarations so the defaults apply.

Example fix

// before
"frontends": []  // plugin declares only unsupported frontends
// after
"frontends": ["desktop", "mobile"]
Defensive patterns

Strategy: validation

Validate before calling

function resolvesToFrontend(manifestF, pluginF) { const has = a => (a || []).some(f => f === "desktop" || f === "mobile"); return has(manifestF) ? has(manifestF) : (has(pluginF) || ((manifestF || []).length === 0 && (pluginF || []).length === 0)); }

Try / catch

try { await installBootAppearance(pkg); } catch (e) { if (String(e).includes("no supported frontend")) { /* declare desktop/mobile in manifest frontends */ } else throw e; }

Prevention

When it happens

Trigger: Manifest omits frontends (so the manifest defaults do not run) but the plugin's frontends list excludes both desktop and mobile; or an empty-but-present combination leaves len(frontends)==0 with non-empty pluginFrontends.

Common situations: A plugin package targeting only an unsupported frontend, or configuration drift between the manifest and the plugin's declared frontends.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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