netbirdio/netbird · error
invalid hash format
Error message
invalid hash format
What it means
Sentinel error argon2id.ErrInvalidHash (shared/hash/argon2id/argon2id.go:24), returned by decodeHash when Verify(secret, encodedHash) receives a string that is not a well-formed Argon2id PHC hash. The expected shape is exactly six $-separated parts: $argon2id$v=19$m=19456,t=2,p=1$<base64 salt>$<base64 hash>. Failures include wrong part count, a non-argon2id prefix, malformed version/parameter segments, or base64-decodable-but-invalid salt/hash fields; each is wrapped with detail (%w).
Source
Thrown at shared/hash/argon2id/argon2id.go:24
"encoding/base64"
"errors"
"fmt"
"strings"
"golang.org/x/crypto/argon2"
)
const (
argon2Memory = 19456
argon2Iterations = 2
argon2Parallelism = 1
argon2SaltLength = 16
argon2KeyLength = 32
)
var (
// ErrInvalidHash is returned when the hash string format is invalid
ErrInvalidHash = errors.New("invalid hash format")
// ErrIncompatibleVersion is returned when the Argon2 version is not supported
ErrIncompatibleVersion = errors.New("incompatible argon2 version")
// ErrMismatchedHashAndPassword is returned when password verification fails
ErrMismatchedHashAndPassword = errors.New("password does not match hash")
)
func Hash(secret string) (string, error) {
salt := make([]byte, argon2SaltLength)
if _, err := rand.Read(salt); err != nil {
return "", fmt.Errorf("failed to generate salt: %w", err)
}
hash := argon2.IDKey(
[]byte(secret),
salt,
argon2Iterations,View on GitHub (pinned to 93e97f4bf1)
Solutions
- Inspect the stored hash and compare it to the canonical form $argon2id$v=19$m=19456,t=2,p=1$<salt>$<hash> produced by argon2id.Hash
- If the stored value comes from another algorithm, verify with that algorithm or force a password reset and store a fresh argon2id.Hash result
- Fix the storage layer: widen the column, stop truncating, and ensure RawStdEncoding base64 survives round-trips
Example fix
// before: stored value was produced by bcrypt stored := "$2a$10$abcdef..." // argon2id.Verify -> invalid hash format // after: hash with argon2id when setting the password stored, err := argon2id.Hash(password) // "$argon2id$v=19$m=19456,t=2,p=1$...$..."
Defensive patterns
Strategy: type-guard
Type guard
// isArgon2idHash reports whether s is a decodable argon2id PHC string
func isArgon2idHash(s string) bool {
parts := strings.Split(s, "$")
if len(parts) != 6 || parts[1] != "argon2id" {
return false
}
var v int
if _, err := fmt.Sscanf(parts[2], "v=%d", &v); err != nil {
return false
}
var m, t uint32
var p uint8
if _, err := fmt.Sscanf(parts[3], "m=%d,t=%d,p=%d", &m, &t, &p); err != nil {
return false
}
salt, err1 := base64.RawStdEncoding.DecodeString(parts[4])
hash, err2 := base64.RawStdEncoding.DecodeString(parts[5])
return err1 == nil && err2 == nil && len(salt) > 0 && len(hash) > 0
} Try / catch
if err := argon2id.Verify(password, stored); err != nil {
if errors.Is(err, argon2id.ErrInvalidHash) {
// data problem, not a wrong password: quarantine the record, log the stored
// hash's prefix (never the full value), and force a reset. Do NOT retry.
}
return err
} Prevention
- Always create stored hashes with argon2id.Hash so the format is canonical
- Size the storage column generously (PHC strings are ~80-100 chars) and test round-trips
- On login, distinguish ErrInvalidHash (data corruption) from ErrMismatchedHashAndPassword (wrong password); never count a format error as an auth failure
When it happens
Trigger: Calling argon2id.Verify with a value produced by a different hasher (bcrypt $2b$..., argon2i, SHA), a hash truncated by a DB column, a hash with standard (padded) base64 instead of RawStdEncoding, or an empty/garbage string.
Common situations: Migrating a user store from another password scheme without rehashing; VARCHAR column too short so the stored hash is cut; JSON/YAML round-trips that mangle the $ characters; passing the plaintext instead of the stored hash by mistake.
Related errors
- incompatible argon2 version
- parse IP %s
- management client is not initialised
- profile not found
- watcher closed unexpectedly
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/061091538981ba19.
Report an issue: GitHub.