siyuan-note/siyuan · error · Error
Unsupported shortcut binding version
Error message
Unsupported shortcut binding version
What it means
setKeymapBindings enforces that an IShortcutKeymap carrying a bindings object uses bindings.version === 1. If a bindings object exists with any other version, the library throws because it cannot safely interpret or migrate an unknown binding format. Maps without a bindings field are fine and are initialized to version 1.
Solutions
- Remove or reset the bindings field on the keymap item so it is regenerated as version 1
- Update the app to the version that wrote the newer bindings format
- Delete the stale keymap JSON and let the app rebuild default bindings
- Catch the error and reinitialize item.bindings to {version: 1} before retrying
Example fix
// before setKeymapBindings(item, keys); // item.bindings.version === 2 // after delete item.bindings; // or migrate version 2 to version 1 setKeymapBindings(item, keys);
Defensive patterns
Strategy: validation
Validate before calling
if (item.bindings && item.bindings.version !== 1) {
delete item.bindings; // reset unknown format before calling
}
setKeymapBindings(item, keys); Type guard
const isV1 = (item) => !item.bindings || item.bindings.version === 1;
Try / catch
try { setKeymapBindings(item, keys); } catch (e) { if (e.message.includes("binding version")) { delete item.bindings; setKeymapBindings(item, keys); } } Prevention
- Do not hand-edit keymap JSON bindings versions
- Upgrade the app instead of loading newer keymap formats into older versions
- Reset bindings to defaults when format errors occur
When it happens
Trigger: Calling setKeymapBindings (app/src/util/keymapBindings.ts:47) with an item whose bindings.version is absent-but-object? no — present and not 1: e.g. bindings: {version: 2, ...} produced by a newer/older app version or hand-edited JSON in the keymap config.
Common situations: Downgrading the app after keymap format changed; merging keymap JSON from another user/installation; plugins or sync writing newer binding versions; hand-editing appearance config files.
Related errors
- A public HTTPS OIDC redirect URL is required for remote…
- Argon2id Iterations too high (maximum 10)
- Argon2id Memory too high (maximum 256 MB)
- Argon2id Parallelism must be between 1 and 16
- builtin color must not be null
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/ad9cc314a69ef61e.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/util/keymapBindings.ts:47
bindings?: IShortcutBindings;
}
export const getKeymapBindings = (item?: IShortcutKeymap): string[] => {
if (!item) {
return [];
}
if (item.bindings) {
if (item.bindings.version !== 1 || !Array.isArray(item.bindings.keys)) {
return [];
}
return [...new Set(item.bindings.keys.filter((key): key is string => typeof key === "string" && key.length > 0))];
}
return typeof item.custom === "string" && item.custom ? [item.custom] : [];
};
export const setKeymapBindings = (item: IShortcutKeymap, keys: string[]) => {
if (item.bindings && item.bindings.version !== 1) {
throw new Error("Unsupported shortcut binding version");
}
const uniqueKeys = [...new Set(keys.filter(Boolean))];
const priority = Object.fromEntries(Object.entries(item.bindings?.priority || {})
.filter(([key]) => uniqueKeys.some(hotkey => key === hotkey || key.endsWith(":" + hotkey))));
item.bindings = {...item.bindings, version: 1, keys: uniqueKeys, priority};
item.custom = uniqueKeys[0] || "";
};
export const getKeymapItem = (keymap: object, path: readonly string[]): IShortcutKeymap | undefined => {
let value: unknown = keymap;
for (const key of path) {
if (!value || typeof value !== "object" || !Object.prototype.hasOwnProperty.call(value, key)) {
return undefined;
}
value = (value as Record<string, unknown>)[key];
}
return value && typeof value === "object" && typeof (value as IShortcutKeymap).custom === "string" ?
value as IShortcutKeymap : undefined;View on GitHub (pinned to 9f775e8a12)