kataras/iris · error

unknown value type of %T

Error message

unknown value type of %T

What it means

The Redis session database's decodeValue switches on the dynamic type returned from Redis: []byte (the common case) or string (from HGetAll). Any other type stored or returned cannot be decoded into the caller's out pointer, so it fails with this error reporting the unexpected Go type via %T.

Source

Thrown at sessions/sessiondb/redis/database.go:222

	}

	return nil
}

func (db *Database) decodeValue(val any, outPtr any) error {
	if val == nil {
		return nil
	}

	switch data := val.(type) {
	case []byte:
		// this is the most common type, as we save all values as []byte,
		// the only exception is where the value is string on HGetAll command.
		return sessions.DefaultTranscoder.Unmarshal(data, outPtr)
	case string:
		return sessions.DefaultTranscoder.Unmarshal([]byte(data), outPtr)
	default:
		return fmt.Errorf("unknown value type of %T", data)
	}
}

func (db *Database) keys(fullSID string) []string {
	keys, err := db.c.Driver.GetKeys(fullSID)
	if err != nil {
		db.logger.Debugf("unable to get all redis keys of session '%s': %v", fullSID, err)
		return nil
	}

	return keys
}

// Visit loops through all session keys and values.
func (db *Database) Visit(sid string, cb func(key string, value any)) error {
	kv, err := db.c.Driver.GetAll(db.makeSID(sid))
	if err != nil {
		return err

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Ensure session values are always written through the same Database/Transcoder so they are stored as []byte.
  2. Clear the affected Redis keys (FLUSHDB or targeted DEL) so stale/foreign values are removed.
  3. Inspect the offending key's Redis TYPE; if it's hash/list/etc. set by external code, migrate it to a plain string/[]byte.
  4. Use a compatible DefaultTranscoder on both the writing and reading sides.

Example fix

// before (external write)
redis-cli HSET sessions:sid key value
// after
sess.Set("key", "value") // library encodes as []byte internally
Defensive patterns

Strategy: try-catch

Validate before calling

t, err := rdb.Type(ctx, "sessions:"+sid).Result()
if t != "string" {
    return fmt.Errorf("session key has redis type %q; expected string", t)
}

Type guard

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

Try / catch

if err := db.Decode(key, out); err != nil {
    if strings.HasPrefix(err.Error(), "unknown value type of") {
        // purge foreign-format key and re-create session
        rdb.Del(ctx, key)
        return newSession()
    }
    return err
}

Prevention

When it happens

Trigger: Decode/Visit on a Redis-backed session DB when the raw value stored in Redis is neither []byte nor string — typically after data was written by a different client/tool or a different session library version.

Common situations: Manually seeding Redis session keys with native Redis types (lists, hashes, ints via redis-cli), upgrading iris/sessions versions with old serialized values, or mixing transcoders between writers and readers.

Related errors


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