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.

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)

Solutions

  1. 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.
  2. Trigger a position rebalance/normalization for the affected list so all positions return to a small range.
  3. Guard client-side: refuse to use an anchor whose position is not a finite, modestly-sized number.
  4. 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

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


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/27a2e6fe8d050272. Report an issue: GitHub.