siyuan-note/siyuan · warning
invalid card aspect ratio [%v]
Error message
invalid card aspect ratio [%v]
What it means
Returned by setAttrViewCardAspectRatioValue (attribute_view.go:1197), dispatched through the transaction action "setAttrViewCardAspectRatioValue". Unlike the preset action (error 426), this accepts a free-form width/height ratio. The value must be finite (not NaN/Inf) and within [av.CardAspectRatioValueMin=0.25, av.CardAspectRatioValueMax=2.5].
Source
Thrown at kernel/model/attribute_view.go:1197
err = av.SaveAttributeView(attrView)
return
}
func (tx *Transaction) doSetAttrViewCardAspectRatioValue(operation *Operation) (ret *TxErr) {
if err := setAttrViewCardAspectRatioValue(operation); nil != err {
return &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()}
}
return
}
func setAttrViewCardAspectRatioValue(operation *Operation) (err error) {
ratio, err := getAttrViewOperationNumber(operation)
if nil != err {
return
}
if math.IsNaN(ratio) || math.IsInf(ratio, 0) ||
ratio < av.CardAspectRatioValueMin || av.CardAspectRatioValueMax < ratio {
return fmt.Errorf("invalid card aspect ratio [%v]", ratio)
}
attrView, err := av.ParseAttributeView(operation.AvID)
if err != nil {
return
}
view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
if err != nil {
return
}
switch view.LayoutType {
case av.LayoutTypeTable:
return
case av.LayoutTypeGallery:
view.Gallery.CardAspectRatioValue = ratio
case av.LayoutTypeKanban:
view.Kanban.CardAspectRatioValue = ratioView on GitHub (pinned to 251596fc0d)
Solutions
- Clamp the custom ratio to the [0.25, 2.5] window before sending (the UI slider should enforce this).
- Guard against NaN/Inf when the ratio is derived from a division (check the divisor).
- If the value is a whole preset, prefer the preset action (setAttrViewCardAspectRatio) which also keeps CardAspectRatioValue in sync.
Example fix
// before: unguarded division can yield Infinity
transaction({ op: "setAttrViewCardAspectRatioValue", data: width / height })
// after: clamp into the valid window
const r = width / height
const ratio = Number.isFinite(r) ? Math.min(2.5, Math.max(0.25, r)) : 16/9
transaction({ op: "setAttrViewCardAspectRatioValue", data: ratio }) Defensive patterns
Strategy: validation
Validate before calling
// Clamp the custom ratio into [0.25, 2.5] and reject non-finite values.
if (!Number.isFinite(ratio)) throw new Error('ratio must be finite')
const safe = Math.min(2.5, Math.max(0.25, ratio)) Type guard
function isValidAspectRatioValue(v: unknown): v is number {
return typeof v === 'number' && Number.isFinite(v) && v >= 0.25 && v <= 2.5
} Prevention
- Clamp the slider/text input to 0.25–2.5 on the client.
- Guard against division by zero when computing width/height.
- Prefer the preset action for standard ratios to keep CardAspectRatioValue in sync.
When it happens
Trigger: Frontend sends a setAttrViewCardAspectRatioValue transaction whose data is NaN/Inf or outside 0.25–2.5. This is the custom-ratio path used when the user types a free value rather than picking a preset.
Common situations: User types 0 or a negative number in a custom ratio field; plugin computes ratio/0 producing Inf or 0/0 producing NaN; value persisted from an older build with different bounds replayed after the bounds tightened.
Related errors
- invalid card aspect ratio preset [%v]
- invalid card size preset [%v]
- invalid card width [%v]
- invalid card layout [%v]
- invalid card field full row value [%v]
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/5220b43fa843fc2d.
Report an issue: GitHub.