larksuite/cli · error · ValueError
anchor outside sheet: {position!r}
Error message
anchor outside sheet: {position!r} What it means
A whole-skill remap (source Ref without a Path) must map to a bare target skill (Ref without a Path). skillref.New rejects mixing granularities because a whole-skill rename cannot project to a single exact file reference for every path under the skill.
Source
Thrown at skills/lark-sheets/scripts/lark_chart_layout_check.py:159
if sheet_identifier(sheet) == sheet_id or sheet_title(sheet) == title:
charts = sheet.get("charts")
return [chart for chart in charts if isinstance(chart, dict)] if isinstance(charts, list) else []
charts = data.get("charts")
return [chart for chart in charts if isinstance(chart, dict)] if isinstance(charts, list) else []
def chart_rectangle(
chart: dict[str, Any], row_edges: list[float], column_edges: list[float]
) -> dict[str, Any]:
details = chart.get("details") if isinstance(chart.get("details"), dict) else chart
position = details.get("position") if isinstance(details.get("position"), dict) else {}
offset = details.get("offset") if isinstance(details.get("offset"), dict) else {}
size = details.get("size") if isinstance(details.get("size"), dict) else {}
row = int(position["row"])
column = column_to_index(str(position["col"]))
if row < 0 or column < 0 or row >= len(row_edges) - 1 or column >= len(column_edges) - 1:
raise ValueError(f"anchor outside sheet: {position!r}")
width = float(size["width"])
height = float(size["height"])
if width <= 0 or height <= 0:
raise ValueError(f"invalid chart size: {size!r}")
left = column_edges[column] + float(offset.get("col_offset", 0) or 0)
top = row_edges[row] + float(offset.get("row_offset", 0) or 0)
return {
"chart_id": str(chart.get("chart_id") or chart.get("id") or ""),
"anchor_cell": f"{index_to_column(column)}{row + 1}",
"left": left,
"top": top,
"right": left + width,
"bottom": top + height,
"width": width,
"height": height,
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Make the target a bare skill reference (no path) to rename the whole skill, e.g. auth -> new-auth.
- If you actually want an exact-reference override, give the source a path too (e.g. auth/login.md -> new-skill/login.md) so both sides are exact.
- Split the intent: one whole-skill rename entry plus separate exact overrides if only some paths should differ.
Example fix
// before
{From: skillref.Ref{Skill: "auth"}, To: skillref.Ref{Skill: "auth-v2", Path: "login.md"}}
// after
{From: skillref.Ref{Skill: "auth"}, To: skillref.Ref{Skill: "auth-v2"}} Defensive patterns
Strategy: validation
Validate before calling
func validateGranularity(m skillref.Mapping) error {
if m.From.Path == "" && m.To.Path != "" {
return fmt.Errorf("whole-skill remap %q needs a bare target, got %q", m.From.String(), m.To.String())
}
return nil
} Type guard
func isWholeSkillRef(r skillref.Ref) bool { return r.Path == "" } Prevention
- Keep whole-skill renames and exact overrides as clearly separated config sections.
- Validate mapping granularity before constructing the Resolver.
- Document that a pathless source requires a pathless target.
When it happens
Trigger: Calling skillref.New with a Mapping whose From.Path == "" but whose To has a non-empty Path (e.g. remap skill 'auth' -> 'skills/auth/login.md').
Common situations: Confusing whole-skill rename entries with exact-reference override entries when editing overlay configs; a tool that rewrites one entry type into the other without normalizing the target.
Related errors
- Invalid column: {column!r}
- Missing row_count/column_count for sheet {sheet_title(sheet)
- Invalid column index: {index}
- invalid chart size: {size!r}
- Missing sheet_id for sheet {title!r}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/2236b4ec56a1627a.
Report an issue: GitHub.