ruvnet/RuView · error · ValueError
Invalid axis token {token!r}; expected one of {sorted(_AXIS_
Error message
Invalid axis token {token!r}; expected one of {sorted(_AXIS_TOKENS)} What it means
parse_axis converts a signed-axis token into a room-frame unit vector for calibration options. Tokens are matched after strip().lower(), so case and surrounding whitespace are tolerated, but the sign is mandatory: only +x, -x, +y, -y, +z, -z are accepted. Anything else raises ValueError listing the sorted valid tokens.
Source
Thrown at scripts/calibration_lib.py:61
# Default checkerboard: 9x6 inner corners, 25 mm squares (a common print).
DEFAULT_BOARD_COLS = 9
DEFAULT_BOARD_ROWS = 6
DEFAULT_SQUARE_SIZE_MM = 25.0
_AXIS_TOKENS = {
"+x": (1.0, 0.0, 0.0), "-x": (-1.0, 0.0, 0.0),
"+y": (0.0, 1.0, 0.0), "-y": (0.0, -1.0, 0.0),
"+z": (0.0, 0.0, 1.0), "-z": (0.0, 0.0, -1.0),
}
def parse_axis(token: str) -> np.ndarray:
"""Parse an axis token like '+x' or '-z' into a room-frame unit vector."""
key = token.strip().lower()
if key in _AXIS_TOKENS:
return np.array(_AXIS_TOKENS[key], dtype=np.float64)
raise ValueError(f"Invalid axis token {token!r}; expected one of {sorted(_AXIS_TOKENS)}")
# ---------------------------------------------------------------------------
# Checkerboard geometry
# ---------------------------------------------------------------------------
def board_object_points(cols: int, rows: int, square_size_m: float) -> np.ndarray:
"""Inner-corner positions in the board's own frame (z=0 plane), row-major.
Matches the corner ordering of cv2.findChessboardCorners for a
(cols, rows) pattern: cols varies fastest.
"""
pts = np.zeros((rows * cols, 3), dtype=np.float64)
grid = np.mgrid[0:cols, 0:rows].T.reshape(-1, 2) # (rows*cols, 2), cols fastest
pts[:, :2] = grid * square_size_m
return pts
View on GitHub (pinned to 4685618388)
Solutions
- Use a signed token: one of +x -x +y -y +z -z (case-insensitive)
- Map descriptive words to signed axes in your wrapper (up → +z, west → -x) before invoking the script
- Copy the accepted set from the error message, which prints sorted(_AXIS_TOKENS)
Example fix
# before python calibrate.py --board-normal z # ValueError: Invalid axis token 'z' # after python calibrate.py --board-normal +z
Defensive patterns
Strategy: type-guard
Validate before calling
AXIS_TOKENS = {"+x", "-x", "+y", "-y", "+z", "-z"}
if axis_arg.strip().lower() not in AXIS_TOKENS:
raise SystemExit(f"axis must be one of {sorted(AXIS_TOKENS)}") Type guard
def is_valid_axis_token(token: str) -> bool:
return isinstance(token, str) and token.strip().lower() in {
"+x", "-x", "+y", "-y", "+z", "-z"
} Try / catch
try:
axis = parse_axis(token)
except ValueError as e:
raise SystemExit(f"bad axis argument: {e}") from e Prevention
- Document signed-axis tokens in wrapper scripts and help text
- Normalize descriptive words (up/down) to signed tokens in your own CLI layer
- Validate config axes at startup, not at first calibration use
When it happens
Trigger: Passing 'x' or 'Z' (missing sign), or words like 'up'/'north', to any CLI option parsed by parse_axis (e.g. --board-normal, axis options of the calibration scripts).
Common situations: Assuming a bare axis letter works; using ceiling/floor vocabulary instead of signed room-frame axes; stray punctuation in config values.
Related errors
- {path}: expected {{'nodes': [...]}} or a top-level list
- invalid privacy class {s!r}; expected one of {list(m.keys())
- {path}: each node needs 'id' and 'position_m' [x,y,z]
- Intrinsics file {path} missing key {key!r}
- Calibration bundle {path} missing key {key!r}
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/0c80c178f282be03.
Report an issue: GitHub.