nexu-io/open-design · error · Error
invalid array segment in template binding path: ${rawPath}
Error message
invalid array segment in template binding path: ${rawPath} What it means
Thrown by walkPath during template binding resolution when the current value is an Array but the next path segment is not a decimal integer (not /^\d+$/). Arrays can only be indexed numerically inside a binding path; any non-numeric segment (e.g. a property name) on an array is a path/type mismatch and is rejected rather than silently returning empty, so the author knows the path disagrees with the data shape.
Source
Thrown at apps/daemon/src/live-artifacts/render.ts:61
.replaceAll('"', '"')
.replaceAll("'", ''');
}
/**
* A binding resolver for one scope. Given a trimmed binding path (e.g.
* `data.title` or a loop variable path like `item.label`) it returns the
* already-escaped scalar string to substitute, or throws for an unsupported
* path. Loop scopes delegate non-matching heads (including `data.*`) to their
* parent so global bindings keep working inside a repeat.
*/
type BindingResolver = (binding: string) => string;
function walkPath(root: unknown, segments: string[], rawPath: string): unknown {
let current: unknown = root;
for (const segment of segments) {
if (current === null || current === undefined) return '';
if (Array.isArray(current)) {
if (!/^\d+$/.test(segment)) throw new Error(`invalid array segment in template binding path: ${rawPath}`);
current = current[Number(segment)];
continue;
}
if (typeof current !== 'object') return '';
current = (current as Record<string, unknown>)[segment];
}
return current ?? '';
}
function readTemplatePath(dataJson: BoundedJsonObject, rawPath: string): unknown {
const segments = rawPath.split('.');
if (segments.shift() !== 'data') throw new Error(`unsupported template binding path: ${rawPath}`);
return walkPath(dataJson, segments, rawPath);
}
function scalarOrThrow(value: unknown, binding: string): string {
if (Array.isArray(value) || (value !== null && typeof value === 'object')) {
throw new Error(`template binding must resolve to a scalar: ${binding}`);View on GitHub (pinned to 5be4028344)
Solutions
- If the value is a list you want to render, use the repeat directive: data-od-repeat="item in data.items" then bind {{item.name}}.
- If you need a single element, index it numerically: {{data.items.0.name}}.
- Confirm the data shape in data.json matches the path; if the source switched from object to array, update the template or restructure the data.
Example fix
// before (data.items is an array)
<div>{{data.items.name}}</div>
// after
<div data-od-repeat="item in data.items">{{item.name}}</div> Defensive patterns
Strategy: type-guard
Validate before calling
function isArrayIndex(seg: string): boolean { return /^\d+$/.test(seg); }
function resolveArray(root: unknown[], path: string[]): unknown {
let cur: unknown = root;
for (const seg of path) {
if (!Array.isArray(cur) || !/^\d+$/.test(seg)) throw new Error('invalid array segment');
cur = cur[Number(seg)];
}
return cur;
} Type guard
function isNumericSegment(seg: string): boolean { return /^\d+$/.test(seg); } Prevention
- Confirm data shape before authoring paths; arrays need numeric indices.
- Use the repeat directive rather than indexing when you want every element.
- Keep a fixture of data.json next to the template during authoring.
When it happens
Trigger: Binding {{data.items.name}} where data.items is an array (should be data.items.0.name or a repeat loop); {{data.list.length}} on an array; any time a path treats an array element as an object before indexing into it.
Common situations: Model writes a property-style path over a list returned by the refresh source (e.g. public_github_repository_metric or git.summary); data shape changed (object became array) and the template wasn't updated; misunderstanding that arrays require numeric indices in this minimal DSL.
Related errors
- unsupported template binding path: ${rawPath}
- invalid template binding path: ${binding}
- template binding must resolve to a scalar: ${binding}
- connector refresh source requires connector metadata
- ${field} must be a dot-separated JSON path
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/4a91358830b0f8ba.
Report an issue: GitHub.