Repository navigation
p5.strands transpilation error gives no context about the callback #9317
Description
Most appropriate sub-area of p5.js?
- Accessibility
- Color
- Core/Environment/Rendering
- Data
- DOM
- Events
- Image
- IO
- Math
- Typography
- Utilities
- WebGL
- WebGPU
- p5.strands
- Build process
- Unit testing
- Internationalization
- Friendly errors
- Other (specify if possible)
p5.js version
2.4.0-rc.1
Web browser and version
Chromium 153.0.8010.12, running p5.js 2.4.0-rc.1 from cdn.jsdelivr.net, which is the same build the p5.js Web Editor loads
Operating system
macOS
Steps to reproduce this
Steps:
- Open the p5.js Web Editor and start a new sketch.
- Paste the snippet below as-is. It is a complete sketch, nothing else is needed.
- Run the sketch and open the browser console.
Snippet:
function setup() {
createCanvas(200, 200, WEBGL);
const fn = () => {};
buildMaterialShader(fn.bind(null));
}Console output
🌸 p5.js says: p5.strands shaders are experimental, so functions for building shaders and the hooks available within them may change in future versions. You can get involved by giving feedback to help direct its development! For more info, see https://p5js.org/contribute/p5.strands/
Uncaught (in promise) SyntaxError: Unexpected token (1:23)
Captured in Chromium 153 against the same p5@2.4.0-rc.1 build the Web Editor loads, from a local page. Running it in the Web Editor gives the same two lines.
What I expected
One legible error that names the problem in my callback and points at it, the way the rest of the friendly error system does.
What actually happened
A raw acorn SyntaxError with no mention of p5.strands and no pointer to the callback. The stack the browser shows is ten frames of acorn internals, so it does not even show which p5 function was involved. Setting Error.stackTraceLimit = 100 shows the rest of the chain:
at parse (p5.js:82651)
at transpileStrandsToJS (p5.js:114210)
at p5.Shader.modify (p5.js:116671)
at fn.buildMaterialShader (p5.js:58459)
The line numbers above are from the published 2.4.0-rc.1 bundle. In the source tree this is the parse() call inside transpileStrandsToJS(), in src/strands/strands_transpiler.js (around line 2116).
The cause is that p5.strands rebuilds the callback from its source text, and the source of a bound function is function () { [native code] }, which is not valid JavaScript. The failure happens inside acorn's parse(), before buildStrandsCallback() is reached, so none of the strands error handling runs and the user is left with an acorn error that mentions neither p5.strands nor their callback.
A callback source that is not valid JavaScript fails the same way:
function setup() {
createCanvas(200, 200, WEBGL);
buildMaterialShader('void main(){}');
}Uncaught (in promise) SyntaxError: Unexpected token (1:12)
Possible approach
- Wrap the
parse()call intranspileStrandsToJS()so a syntax error in the callback source becomes a strands friendly error instead of escaping as a raw acornSyntaxError. The message should say that the callback source could not be parsed, and show the offending position, e.g.Unexpected token (1:23). - Detect the case where the callback source is not usable at all, such as a bound function, whose
toString()isfunction () { [native code] }, and say that directly, since no amount of position information helps there. - Leave the two paths in [p5.js 2.0+ Bug Report] : p5.strands error paths dump internals to console before throwing #9310 unchanged, so this can be a separate change.
Happy to fix this myself once an approach is agreed on.
Related issues
- [p5.js 2.0+ Bug Report]: p5.strands: the ** operator crashes the transpiler with an error pointing at p5.js internals #9252 is the same shape of problem from a different trigger. There, an unsupported operator crashes inside the transpiler and the error points at p5.js internals. Here, the callback source cannot be parsed at all, and the error is a raw acorn
SyntaxError. - Better error messages for bad property access in p5.strands #9218 is about a runtime error inside a strands callback whose message stringifies internal state. The open PR for it, Improve error message for non-numeric strands construction (#9218) #9229, targets a different throw site in
src/strands/ir_builders.js, and it leaves stack-trace filtering and source mapping as follow-ups. What I am reporting here happens earlier, during transpilation, and never reaches the strands error handling at all. - [p5.js 2.0+ Bug Report] : p5.strands error paths dump internals to console before throwing #9310 covers the two paths that dump the parsed program, or the parameter names and body, to the console before throwing. It was confirmed on 2.4.0-rc.1 and closed. This issue is about the path that was not covered, where the user gets no legible response at all.
I did not want to reopen #9310 for this, since it looks like a separate failure mode, but happy to fold it in if that is easier.
Scope
This one is entirely inside p5.strands, in src/strands/strands_transpiler.js. I am happy to work on it, and happy to pair with @subhranshudash13-dotcom, who offered to pick up the strands side of #9310. I can also see @LalitNarayanYadav working on #9218 and @harshiltewari2004 on #9252, so I would rather not step on either of you, happy to coordinate.
There is a related problem in the friendly error system's parameter validator, where the message comes out empty and the raw Zod error object is logged for callback parameters. That one is outside p5.strands, and it may already be covered by #9209, so I will look into it separately rather than file it right away.
Metadata
Metadata
Assignees
Type
Projects
- StatusShow more project fieldsNo status
Activity
welcome commentedon Oct 22, 2026
Welcome! 👋 Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, please make sure to fill out the inputs in the issue forms.
For guidance on contributing, check out our contributing guidelines and other resources for contributors.
💬 If you have questions or need support, feel free to join the Processing Foundation Forum or visit our Community page.
📜 Please also review our Code of Conduct to understand our community standards.
Thank You!
davepagurek commentedon Oct 23, 2026
Agreed that we should have a more helpful error here. We possibly can try to handle all the cases you mention? e.g. we could have a special error when we see
[native code]in the stringification to give more specific guidance ("did you use.bind(...)on a function?") as well as just providing a clearer error (ideally with a line number) when there's a syntax problem.AdeshDeshmukh commentedon Oct 23, 2026
I'm happy to take this on. Here's the approach I'm thinking of:
Detect bound functions before parsing — check if the callback's stringified source contains
[native code](which happens with.bind(...)). If so, throw a direct, user-friendly error like "did you use.bind(...)on a function?" since no line number helps there.Wrap
parse()intranspileStrandsToJS()— catch anySyntaxErrorfrom acorn and re-throw it as a strands-friendly error that includes the line and column position so the user can find the typo in their callback.Leave valid callbacks untouched — no console dumps, no behavior change for working code.
Does this match what you had in mind? I'll wait for your thumbs-up before writing any code.
AdeshDeshmukh commentedon Oct 23, 2026
I have a question regarding the error style for this..!
For these two cases — the bound-function check and the wrapped
parse()error — should the errors route throughstrands_FES(userError/internalError) like the other p5.strands errors, or should they be plain thrownErrors?I want to match the existing error style in the codebase so it feels consistent for users.
I would like to have your opinion on this.!