cloudreve/cloudreve · error · ErrTypeNotMatch
mismatched ID type.
Error message
mismatched ID type.
What it means
hashid.ErrTypeNotMatch is returned by hashEncoder.Decode when the decoded hashids payload does not have exactly two numbers or the second number (the embedded type tag) differs from the requested type t. Cloudreve encodes every public ID as a pair [id, TypeID] (ShareID=0, UserID=1, FileID=2, ...), so a hash string is only valid for the one type it was created with.
Source
Thrown at pkg/hashid/hash.go:29
ShareID = iota // 分享
UserID // 用户
FileID // 文件ID
FolderID // 目录ID
TagID // 标签ID
PolicyID // 存储策略ID
SourceLinkID
GroupID
EntityID
AuditLogID
NodeID
TaskID
DavAccountID
PaymentID
)
var (
// ErrTypeNotMatch ID类型不匹配
ErrTypeNotMatch = errors.New("mismatched ID type.")
)
type Encoder interface {
Encode(v []int) (string, error)
Decode(raw string, t int) (int, error)
}
// ObjectIDCtx define key for decoded hash ID.
type (
ObjectIDCtx struct{}
EncodeFunc func(encoder Encoder, uid int) string
)
type hashEncoder struct {
h *hashids.HashID
}
func New(salt string) (Encoder, error) {View on GitHub (pinned to 20c95ad73f)
Solutions
- Check which encoder helper produced the hash (EncodeFileID, EncodeShareID, ...) and call Decode with the matching type constant
- Fix the client/frontend to send the ID from the correct field of the API response
- If you changed the iota order of the ID constants, revert it or migrate stored hashes
Example fix
// before id, err := hash.Decode(rawID, hashid.UserID) // rawID is actually a file hash // after id, err := hash.Decode(rawID, hashid.FileID)
Defensive patterns
Strategy: validation
Try / catch
// Go: distinguish type mismatch from malformed hash and map to 400
id, err := encoder.Decode(raw, hashid.FileID)
switch {
case err == nil:
case errors.Is(err, hashid.ErrTypeNotMatch):
return serializer.Err(
code.CodeParamError,
"ID does not belong to this resource type",
nil,
)
default:
return serializer.Err(
code.CodeInvalidRefer,
"malformed ID",
nil,
)
} Prevention
- Keep a single source of truth mapping each API route/param to its hashid type constant
- Always generate public IDs with the EncodeXxxID helpers so the type tag is embedded correctly
- Never reorder the hashid iota constants; append new types only at the end
- In integration tests, verify Decode rejects hashes of every other type
When it happens
Trigger: Calling encoder.Decode(raw, hashid.FileID) on a hash that was generated with EncodeUserID/EncodeShareID/etc.; calling Decode on an arbitrary string that happens to decode to a non-2-element slice; mixing hashes between API endpoints (passing a share ID where a file ID is expected in a URL parameter).
Common situations: Frontend sends the wrong ID field in a request (e.g. uses the share's hash in a file-scoped route); API consumers reuse IDs from one resource type against another endpoint; changing hashid type constants order between versions while keeping old hashes; testing Decode with placeholder strings.
Related errors
- 40001
- unsupported database type %q
- unsupported database type: %s
- failed to decode id: %w
- invalid page token %q: %w
AI-assisted analysis of cloudreve/cloudreve@20c95ad73f (2026-08-16).
Data as JSON: /api/errors/71401d593284725a.
Report an issue: GitHub.