GopeedLab/gopeed · error

panic: %v

Error message

panic: %v

What it means

The stream inject module runs the extension's fetch/stream script on the goja loop under a deferred recover; this 'panic: %v' branch is the fallback when the recovered value is neither an error nor a goja.Value. It indicates native code involved in the fetch/stream binding panicked with a raw value while executing the script, and the error is delivered to the waiting caller via a non-blocking send.

Source

Thrown at pkg/download/engine/inject/stream/module.go:490

		err   error
	}
	ch := make(chan result, 1)
	ok := loop.RunOnLoop(func(runtime *goja.Runtime) {
		send := func(value goja.Value, err error) {
			select {
			case ch <- result{value: value, err: err}:
			default:
			}
		}
		defer func() {
			if r := recover(); r != nil {
				switch v := r.(type) {
				case error:
					send(nil, v)
				case goja.Value:
					send(nil, exportJSError(v))
				default:
					send(nil, fmt.Errorf("panic: %v", r))
				}
			}
		}()
		value, err := fn(runtime)
		if err != nil {
			send(nil, err)
			return
		}
		if promise, ok := value.Export().(*goja.Promise); ok {
			switch promise.State() {
			case goja.PromiseStateFulfilled:
				send(promise.Result(), nil)
				return
			case goja.PromiseStateRejected:
				send(nil, exportJSError(promise.Result()))
				return
			default:
				thenVal := value.ToObject(runtime).Get("then")

View on GitHub (pinned to 7b7327ffb3)

Solutions

  1. Simplify the fetch script to isolate which call panics, then fix the arguments passed to the injected helper
  2. Update/reinstall the extension so its expected binding signatures match the host version
  3. If you own the binding, convert string panics into returned errors so callers get the structured branch instead
Defensive patterns

Strategy: try-catch

Try / catch

// inside the fetch/stream handler
try {
  const res = await runFetchScript(script);
} catch (e) {
  if (String(e).includes("panic:")) {
    // native binding panicked while running the script: report script id, do not retry blindly
    return { err: `fetch script panicked: ${e}` };
  }
  throw e;
}

Prevention

When it happens

Trigger: An extension's fetch handler reaching an injected native binding (request builder, stream opener) that panics with a non-error value; scripts that put the goja runtime into an invalid state (deep recursion, prototype tampering) triggering an internal invariant panic.

Common situations: Extension calling fetch()/open() helpers with malformed option objects after a host update; long-running stream handlers racing a shutdown; a binding version mismatch between host and extension.

Related errors


AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16). Data as JSON: /api/errors/70caa247dc0312e5. Report an issue: GitHub.