siyuan-note/siyuan · error
invalid card cover position [%v, %v]
Error message
invalid card cover position [%v, %v]
What it means
Thrown by setAttrViewCardCoverPosition when a card cover position's X or Y coordinate is NaN, +/-Inf, or outside the allowed [0, 100] range. SiYuan stores cover-image focal position as percentages, so any value below 0 or above 100 (or non-finite) is rejected before the AttributeView is saved. The image itself is validated separately (non-empty and <= 32KB) just above this check.
Source
Thrown at kernel/model/attribute_view.go:1924
dataJSON, err := json.Marshal(operation.Data)
if nil != err {
return
}
var data setAttrViewCardCoverPositionData
if err = json.Unmarshal(dataJSON, &data); nil != err {
return
}
if !av.IsValidCardCoverSource(data.Source) {
return fmt.Errorf("invalid card cover source [%s]", data.Source)
}
if nil != data.Position {
if "" == data.Position.Image || 32*1024 < len(data.Position.Image) {
return errors.New("invalid card cover image")
}
if math.IsNaN(data.Position.X) || math.IsInf(data.Position.X, 0) ||
math.IsNaN(data.Position.Y) || math.IsInf(data.Position.Y, 0) ||
data.Position.X < 0 || 100 < data.Position.X || data.Position.Y < 0 || 100 < data.Position.Y {
return fmt.Errorf("invalid card cover position [%v, %v]", data.Position.X, data.Position.Y)
}
}
attrView, err := av.ParseAttributeView(operation.AvID)
if nil != err {
return
}
if nil == attrView.GetBlockValue(operation.RowID) {
return fmt.Errorf("attribute view item [%s] not found", operation.RowID)
}
view, err := getAttrViewViewByBlockID(attrView, operation.BlockID)
if nil != err {
return
}
if av.LayoutTypeGallery != view.LayoutType && av.LayoutTypeKanban != view.LayoutType {
return av.ErrWrongLayoutType
}
var source stringView on GitHub (pinned to 251596fc0d)
Solutions
- Clamp both X and Y to the inclusive range [0, 100] on the client before sending the operation, and ensure the values are finite numbers.
- If calling the kernel API directly, validate with math.IsNaN/math.IsInf and bound-check before constructing the operation Data.
- Update the frontend to a version matching the kernel so the cover-position contract (percentage 0-100) is honored.
Example fix
// before
op.Data = { source: "content", position: { image: b64, x: rawPxX, y: rawPxY } }
// after
const clamp = v => Math.max(0, Math.min(100, (Number.isFinite(v) ? v : 50)))
op.Data = { source: "content", position: { image: b64, x: clamp(xPct), y: clamp(yPct) } } Defensive patterns
Strategy: validation
Validate before calling
function isValidCoverPosition(p) {
if (p == null) return true // null position clears the entry
return Number.isFinite(p.x) && Number.isFinite(p.y) && p.x >= 0 && p.x <= 100 && p.y >= 0 && p.y <= 100 && typeof p.image === 'string' && p.image.length > 0 && p.image.length <= 32 * 1024
}
if (!isValidCoverPosition(op.data.position)) { /* do not send */ } Type guard
type CardCoverPos = { image: string; x: number; y: number }
function isCardCoverPos(v: unknown): v is CardCoverPos | null {
if (v == null) return true
if (typeof v !== 'object' || v === null) return false
const p = v as Record<string, unknown>
return typeof p.image === 'string' && typeof p.x === 'number' && typeof p.y === 'number' && Number.isFinite(p.x) && Number.isFinite(p.y)
} Prevention
- Clamp position coordinates to [0,100] in the drag handler before they enter state.
- Never store raw pixel offsets in the same field as percentage positions.
- Add a client-side unit test that every emitted position is finite and bounded.
When it happens
Trigger: A transaction operation of action setAttrViewCardCoverPosition whose Data.Position is non-nil with X or Y outside 0..100, or a payload produced by a buggy/older frontend that sends pixel offsets instead of percentages. NaN/Inf reach the check when the JSON payload contains null cast to float64 or a corrupted numeric field.
Common situations: Frontend version skew where an older client sends raw pixel coordinates; a manually crafted API call; a rounding/clamping bug in the drag handler that occasionally yields -0.0001 or 100.0001.
Related errors
- invalid card aspect ratio preset [%v]
- invalid card aspect ratio [%v]
- at least one visible view is required
- view [%s] not found in attribute view [%s]
- block [%s] is not an instance of attribute view [%s]
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/2fa3d174f9876488.
Report an issue: GitHub.