multica-ai/multica · warning
move position is out of range
Error message
move position is out of range
What it means
issueMovePosition's single-anchor branches append with a fixed step: position = before + 1 (move below the anchor) or position = after - 1 (move above it). If that arithmetic overflows to ±Inf or produces NaN — which requires the anchor to be at or near the float64 maximum (or minimum for the subtract branch) — the result is rejected as out of range. In normal operation positions stay near zero, so hitting this indicates corrupted or adversarial position values, not ordinary use.
Solutions
- Identify the corrupted row: query for positions that are NULL, NaN, or outside a sane band (e.g. |pos| > 1e15) and reset them to normal values.
- Trigger a position rebalance/normalization for the affected list so all positions return to a small range.
- Guard client-side: refuse to use an anchor whose position is not a finite, modestly-sized number.
- If caused by writes from another tool, fix that tool to emit bounded positions.
Example fix
// before (corrupted row) UPDATE issue SET position = 1e308 WHERE id = '...'; // after UPDATE issue SET position = 0 WHERE id = '...'; -- or run the list rebalance job
Defensive patterns
Strategy: validation
Validate before calling
const POS_BOUND = 1e15;
function assertAnchorSane(anchor) {
if (!anchor) return;
const p = anchor.position;
if (!Number.isFinite(p) || Math.abs(p) > POS_BOUND) {
throw new Error(`anchor ${anchor.id} has corrupt position ${p}; refetch or rebalance the list`);
}
} Type guard
const isSanePosition = (p) => Number.isFinite(p) && Math.abs(p) < 1e15;
Prevention
- Never write positions from external tools without bounding them to a sane numeric range.
- Add a monitoring query for |position| > 1e15 or non-finite positions to catch corruption early.
- Run the list's rebalance/normalization job when corrupted positions are detected.
When it happens
Trigger: Move with a single before anchor whose stored position is close to math.MaxFloat64 (so +1 rounds to the same value or the value is already Inf), or an after anchor near -MaxFloat64 / equal to -Inf (so -1 yields Inf/NaN behavior). Realistically only reachable via corrupted rows or directly crafted API calls.
Common situations: A bug or manual SQL write leaving an issue position at an extreme value, then dragging relative to it; fuzzing or pen-testing the move endpoint with extreme floats; NaN positions inserted through some other path and used as an anchor.
Related errors
- delete runtime: runtime has active agents bound to it
- move anchors are stale or out of order
- move anchors are too close; refresh and retry
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/27a2e6fe8d050272.
Report an issue: GitHub.
Appendix: source
Thrown at server/internal/handler/issue_move.go:205
return &position, true
}
func issueMovePosition(current float64, before, after *float64) (float64, error) {
switch {
case before != nil && after != nil:
if !(*before < *after) {
return 0, errors.New("move anchors are stale or out of order")
}
position := *before + (*after-*before)/2
if !(position > *before && position < *after) ||
math.IsInf(position, 0) || math.IsNaN(position) {
return 0, errors.New("move anchors are too close; refresh and retry")
}
return position, nil
case before != nil:
position := *before + 1
if math.IsInf(position, 0) || math.IsNaN(position) {
return 0, errors.New("move position is out of range")
}
return position, nil
case after != nil:
position := *after - 1
if math.IsInf(position, 0) || math.IsNaN(position) {
return 0, errors.New("move position is out of range")
}
return position, nil
default:
return current, nil
}
}
View on GitHub (pinned to 2c0912b6ec)