siyuan-note/siyuan · error
promise rejected: %v
Error message
promise rejected: %v
What it means
The handler returned a Promise and invokeFunction attached onFulfilled/onRejected callbacks via .then; the rejection callback fired, so the plugin's async operation rejected. %v is call.Argument(0).Export() — the rejection reason (an Error, string, or value).
Source
Thrown at kernel/plugin/sandbox.go:407
}
thenValue := resultObj.Get("then")
then, ok := goja.AssertFunction(thenValue)
if !ok {
callback(rt, &CallResult{Error: fmt.Errorf("'promise.then property is not a function")})
return
}
then(resultObj, rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) {
// ⚠️ call.Arguments always is an empty array.
promise, ok := result.(*goja.Promise)
if ok {
callback(rt, &CallResult{Value: promise.Result()})
} else {
callback(rt, &CallResult{Value: resultJs})
}
}), rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) {
callback(rt, &CallResult{Error: fmt.Errorf("promise rejected: %v", call.Argument(0).Export())})
}))
} else {
callback(rt, &CallResult{Value: resultJs})
}
}
// isJsPromise checks if a goja.Value is a JavaScript Promise.
func isJsPromise(jsValue goja.Value) bool {
if jsValue == nil {
return false
}
goValue := jsValue.Export()
return isGoPromise(goValue)
}
// isGoPromise checks if a Go value is a *goja.Promise.
func isGoPromise(goValue any) bool {View on GitHub (pinned to 251596fc0d)
Solutions
- Inspect the rejection reason in the error message (the %v) to find the root cause.
- Add try/catch inside the async handler and return a structured error or a safe default instead of rejecting.
- Validate inputs before performing the async operation that rejects.
Example fix
// before
handler = async (req) => { return await fetch(req.url) } // rejects on network error
// after
handler = async (req) => {
try { return await fetch(req.url) }
catch (e) { return { error: e.message } } // resolves instead of rejecting
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate inputs that commonly cause rejection before the async op.
function validateRequest(req: { url?: string }): void {
if (!req.url) throw new Error('missing url')
try { new URL(req.url) } catch { throw new Error('invalid url') }
} Try / catch
// Resolve-with-structured-error instead of letting the Promise reject.
handler = async (req) => {
try { return await doAsync(req) }
catch (e) { return { ok: false, error: String(e) } }
} Prevention
- Wrap async handler bodies in try/catch and resolve with a structured result.
- Validate inputs (URLs, IDs) before the async call that can reject.
- Log the rejection reason locally so root cause is visible without kernel logs.
When it happens
Trigger: An async plugin handler calls reject, throws inside an async function, or awaits a rejected Promise. Surfaced through the registered server/event async hook during request processing.
Common situations: Plugin's fetch to an external service fails (network/404); plugin throws inside async handler due to bad input; uncaught rejection in a chained .then inside the handler.
Related errors
- synchronous function returned a Promise
- expected promise object, got %T
- 'promise.then property is not a function
- path %v: value is nil
- path %v: value is %s
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/98b6783ae7b4f15f.
Report an issue: GitHub.