siyuan-note/siyuan · error

invalid card aspect ratio

Error message

invalid card aspect ratio [%v]

What it means

This error is thrown when an attribute-view transaction operation tries to set a gallery/kanban card aspect ratio to a value that is NaN, infinite, or outside the allowed range [av.CardAspectRatioValueMin, av.CardAspectRatioValueMax]. The kernel validates the ratio number from getAttrViewOperationNumber before parsing or mutating the attribute view, so invalid values never touch stored data.

Solutions

  1. Clamp/validate the ratio client-side against av.CardAspectRatioValueMin and av.CardAspectRatioValueMax before enqueueing the transaction operation.
  2. Ensure the ratio is computed from real rendered dimensions; guard against division by zero or undefined width/height.
  3. Update plugin code to the current CardAspectRatioValue bounds if it was written against an older kernel version.
  4. Retry the operation with a valid finite number within range.

Example fix

// before
const ratio = el.clientWidth / el.clientHeight; // 0 height -> Infinity
pushSetCardAspectRatio(avID, ratio);
// after
const ratio = el.clientHeight > 0 ? el.clientWidth / el.clientHeight : 1;
if (Number.isFinite(ratio) && ratio >= CardAspectRatioValueMin && ratio <= CardAspectRatioValueMax) {
  pushSetCardAspectRatio(avID, ratio);
}
Defensive patterns

Strategy: validation

Validate before calling

function isValidAspectRatio(r) { return typeof r === 'number' && Number.isFinite(r) && r >= CardAspectRatioValueMin && r <= CardAspectRatioValueMax; }
if (!isValidAspectRatio(ratio)) throw new RangeError('aspect ratio out of range');

Type guard

const isFiniteNumber = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v);

Try / catch

try { await setCardAspectRatio(avID, ratio); } catch (e) { if (String(e).includes('invalid card aspect ratio')) { console.warn('ratio rejected, clamping'); await setCardAspectRatio(avID, clamp(ratio)); } else throw e; }

Prevention

When it happens

Trigger: Sending a setAttrViewCardAspectRatio transaction operation (via doSetAttrViewCardAspectRatioValue) whose operation data number is NaN, +/-Inf, negative, or larger than av.CardAspectRatioValueMax.

Common situations: Frontend or plugin computes the ratio from element dimensions that are 0 or not yet laid out (division by zero producing NaN/Inf); stale plugin code using an old ratio range after the kernel added min/max bounds; manual transaction crafting with a typo'd value.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/5220b43fa843fc2d. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/attribute_view.go:1343

	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 = ratio

View on GitHub (pinned to 9f775e8a12)