kataras/iris · error

unsupported type of map: %T

Error message

unsupported type of map: %T

What it means

AllowUsers accepts users as a map[string]string, map[string]any, a slice of maps, or a slice of User-like structs. This panic fires when the `users` argument is a map whose key/value types are neither string/string nor string/any (e.g. map[int]string). It is a deliberate fail-fast at middleware construction time so a bad configuration never reaches serving.

Source

Thrown at middleware/basicauth/user.go:128

			}
		}
	case reflect.Map:
		elem := v.Interface()
		switch m := elem.(type) {
		case map[string]string:
			return userMap(m, opts...)
		case map[string]any:
			username, password, ok := mapUsernameAndPassword(m)
			if !ok {
				break
			}

			cp[username] = &user{
				password: password,
				ref:      m,
			}
		default:
			panic(fmt.Sprintf("unsupported type of map: %T", users))
		}
	default:
		panic(fmt.Sprintf("unsupported type: %T", users))
	}

	options := toUserAuthOptions(opts)

	return func(_ *context.Context, username, password string) (any, bool) {
		if u, ok := cp[username]; ok { // fast map access,
			if options.ComparePassword(u.password, password) {
				return u.ref, true
			}
		}

		return nil, false
	}
}

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Convert the map to map[string]string (or map[string]any) before calling AllowUsers, e.g. via a loop or json round-trip.
  2. If usernames are numeric keys, convert them to strings with strconv when building the map.
  3. If users come from a struct list, pass the slice of structs instead of a map so the Slice branch is used.

Example fix

// before
users := map[int]string{1: "pass"}
h := basicauth.Default(basicauth.Options{Allow: basicauth.AllowUsers(users)})
// after
users := map[string]string{"admin": "pass"}
h := basicauth.Default(basicauth.Options{Allow: basicauth.AllowUsers(users)})
Defensive patterns

Strategy: type-guard

Validate before calling

switch users.(type) {
case map[string]string, map[string]any:
    // ok
default:
    panic(fmt.Sprintf("AllowUsers: unsupported map type %T", users))
}

Type guard

func isSupportedUsersMap(v any) bool {
    switch v.(type) {
    case map[string]string, map[string]any:
        return true
    }
    return false
}

Try / catch

// panics are not recoverable per-call idiom here; guard before:
if !isSupportedUsersMap(users) { log.Fatalf("unsupported users type %T", users) }
allow := basicauth.AllowUsers(users)

Prevention

When it happens

Trigger: Calling AllowUsers with a map other than map[string]string or map[string]any, such as AllowUsers(map[int]string{1: "pass"}) or a typed map alias like map[string][]byte. Non-map, non-slice values instead hit the sibling "unsupported type" panic at line 131.

Common situations: Building the users map from config where usernames were parsed as ints; using a custom map type (type Users map[string]Secret) whose value type is not string/any; passing a nil interface typed as a map with non-string keys.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/e2db692fdb3a13b7. Report an issue: GitHub.