Summary
When using Arrow for agent-generated UIs, we frequently hit:
Error: Invalid HTML position
thrown from template compilation when the number of expression placeholders recovered from template.innerHTML does not match rawStrings.length - 1.
In @arrow-js/core@1.0.6 this is roughly:
template.innerHTML = signature;
const paths = createPaths(template.content);
// ...
if (count !== expressions) {
throw Error('Invalid HTML position');
}
This is understandable given HTML parser rules (comment placeholders can be moved/dropped when expressions land in illegal positions). For coding agents and humans alike, the current error is hard to act on: it does not say which expression was lost, where in the template, or why.
Why this matters
Arrow is positioned as especially good for agent-authored interfaces (tiny docs, no build step). Agents commonly emit patterns that are idiomatic in React/Vue/string templates but illegal for Arrow’s placeholder approach, e.g.:
- mixed static + dynamic attribute text:
class="truncate ${cls}"
- interpolated ids/labels:
id="row-${id}", aria-label="Open ${name}"
- HTML comments inside
html\...``
- whitespace-wrapped table rows:
html` <tr>...</tr> `
- non-
<tr> children under <tbody>
We can paper over this with prompt rules, but a clearer runtime signal (or safer compile path) would reduce a large class of agent failures.
Minimal reproductions
1) Mixed attribute interpolation (very common)
<!doctype html>
<html>
<body>
<div id="app"></div>
<script type="module">
import { html, reactive } from 'https://esm.sh/@arrow-js/core@1.0.6';
const state = reactive({ selected: true, name: 'Pump' });
const nameClass = () => (state.selected ? 'font-semibold text-blue-700' : 'font-semibold text-slate-900');
// Throws: Invalid HTML position
html`<div class="truncate ${nameClass}">${() => state.name}</div>`(document.getElementById('app'));
</script>
</body>
</html>
Works if rewritten to a single full attribute expression:
const assetNameClass = () => `truncate ${nameClass()}`;
html`<div class="${assetNameClass}">${() => state.name}</div>`
2) Interpolated id / aria-label
html`<div id="asset-${() => state.id}"></div>`
// and
html`<button aria-label="Open ${() => state.name}">Open</button>`
Both throw Invalid HTML position. Precomputing the full attribute string works.
3) HTML comment inside template
html`<!-- row --><section>${() => state.name}</section>`
Throws Invalid HTML position (comments collide with Arrow’s placeholder strategy).
4) Related: whitespace around <tr> (also tracked in #124)
html`<tbody>${() => [html` <tr><td>1</td></tr> `]}</tbody>`
Can break rendering / throw depending on updates; related HTML-parser sensitivity.
Expected behavior (DX ask)
Any of these would help a lot for agent + human authors:
- Better error message when placeholder count mismatches, e.g.:
- expected N expressions, found M after HTML parse
- include a short snippet of the offending template signature
- list common causes (mixed attributes, comments, illegal table content, etc.)
- Docs / llms.txt callout with a short “illegal positions” section and wrong/right examples (mixed attrs especially).
- Longer-term (optional): compile-time detection or a more resilient attribute interpolation story so
class="foo ${bar}" either works or fails with an attribute-specific diagnostic instead of a generic position error.
Environment
@arrow-js/core 1.0.6
- Browser Chromium (also reproduced under Puppeteer verification)
- Use case: LLM-generated Arrow apps in a sandboxed iframe
Notes
We understand this may be “working as designed” given innerHTML + comment placeholders. Filing this mainly as a DX / agent-ergonomics request: the failure mode is correct, but the signal is too opaque for the audience Arrow is targeting.
Happy to help refine repros or test patches.
Summary
When using Arrow for agent-generated UIs, we frequently hit:
thrown from template compilation when the number of expression placeholders recovered from
template.innerHTMLdoes not matchrawStrings.length - 1.In
@arrow-js/core@1.0.6this is roughly:This is understandable given HTML parser rules (comment placeholders can be moved/dropped when expressions land in illegal positions). For coding agents and humans alike, the current error is hard to act on: it does not say which expression was lost, where in the template, or why.
Why this matters
Arrow is positioned as especially good for agent-authored interfaces (tiny docs, no build step). Agents commonly emit patterns that are idiomatic in React/Vue/string templates but illegal for Arrow’s placeholder approach, e.g.:
class="truncate ${cls}"id="row-${id}",aria-label="Open ${name}"html\...``html` <tr>...</tr> `<tr>children under<tbody>We can paper over this with prompt rules, but a clearer runtime signal (or safer compile path) would reduce a large class of agent failures.
Minimal reproductions
1) Mixed attribute interpolation (very common)
Works if rewritten to a single full attribute expression:
2) Interpolated id / aria-label
Both throw
Invalid HTML position. Precomputing the full attribute string works.3) HTML comment inside template
Throws
Invalid HTML position(comments collide with Arrow’s placeholder strategy).4) Related: whitespace around
<tr>(also tracked in #124)Can break rendering / throw depending on updates; related HTML-parser sensitivity.
Expected behavior (DX ask)
Any of these would help a lot for agent + human authors:
class="foo ${bar}"either works or fails with an attribute-specific diagnostic instead of a generic position error.Environment
@arrow-js/core1.0.6Notes
We understand this may be “working as designed” given
innerHTML+ comment placeholders. Filing this mainly as a DX / agent-ergonomics request: the failure mode is correct, but the signal is too opaque for the audience Arrow is targeting.Happy to help refine repros or test patches.