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

  1. Inspect the log line 'errors.E: bad call from <file>:<line>' to find the exact call site, then fix the argument types there.
  2. Convert unsupported values: numbers/structs into fmt.Errorf("...", v), and ensure custom error types implement the `error` interface.
  3. 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

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


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)