hibiken/asynq · error
unknown type %T, value
Error message
unknown type %T, value %v in error call
What it means
errors.E builds a structured *errors.Error from variadic arguments (code, string, error). When an argument's type matches none of the accepted kinds, the function logs the bad call site via runtime.Caller and returns this sentinel error instead of a structured one. It signals a programming mistake: E was called with an unsupported argument type.
Solutions
- Inspect the log line 'errors.E: bad call from <file>:<line>' to find the exact call site, then fix the argument types there.
- Convert unsupported values: numbers/structs into fmt.Errorf("...", v), and ensure custom error types implement the `error` interface.
- Only pass errors.Code values (e.g. errors.Internal), strings, or error values to E.
Example fix
// before
return errors.E(errors.Internal, http.StatusText(code), resp.StatusCode)
// after
return errors.E(errors.Internal, fmt.Errorf("unexpected status: %d", resp.StatusCode)) Defensive patterns
Strategy: type-guard
Validate before calling
// ensure only accepted argument types are passed
code := errors.Internal
var errArg error = fmt.Errorf("status %d", resp.StatusCode)
return errors.E(code, errArg) Type guard
func isValidEArg(arg interface{}) bool {
switch arg.(type) {
case nil, string, error:
return true
}
if _, ok := arg.(errors.Code); ok { return true }
return false
} Try / catch
err := doWork()
var e *errors.Error
if errors.As(err, &e) {
// structured error
} else if strings.Contains(err.Error(), "unknown type") {
log.Fatalf("bad errors.E call: %v", err) // fix call site
} Prevention
- Grep for errors.E calls passing non-string, non-error, non-Code arguments during code review.
- Convert numeric/struct context with fmt.Errorf before passing to E.
- Watch the 'errors.E: bad call from <file>:<line>' log output in development to catch misuse early.
When it happens
Trigger: Calling errors.E with any argument other than a Code, a string, or an error value — e.g. errors.E(42), errors.E(someStruct), errors.E(nil), or errors.E(errors.Internal, 123, "msg").
Common situations: Refactors where an int constant is passed instead of errors.Code; passing a custom error wrapper type that is not an `error`; copy-paste from other error libraries where E accepts arbitrary values; passing nil interface as the error argument.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- task id conflicts with another task
- testutil: redis is down
- skip retry for the task
- revoke task
- asynq: task lease expired
AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07).
Data as JSON: /api/errors/bd6b6dfd178dcc9b.
Report an issue: GitHub.
Appendix: source
Thrown at internal/errors/errors.go:142
func E(args ...interface{}) error {
if len(args) == 0 {
panic("call to errors.E with no arguments")
}
e := &Error{}
for _, arg := range args {
switch arg := arg.(type) {
case Op:
e.Op = arg
case Code:
e.Code = arg
case error:
e.Err = arg
case string:
e.Err = errors.New(arg)
default:
_, file, line, _ := runtime.Caller(1)
log.Printf("errors.E: bad call from %s:%d: %v", file, line, args)
return fmt.Errorf("unknown type %T, value %v in error call", arg, arg)
}
}
return e
}
// CanonicalCode returns the canonical code of the given error if one is present.
// Otherwise it returns Unspecified.
func CanonicalCode(err error) Code {
if err == nil {
return Unspecified
}
e, ok := err.(*Error)
if !ok {
return Unspecified
}
if e.Code == Unspecified {
return CanonicalCode(e.Err)
}View on GitHub (pinned to d135f1439b)