router-for-me/CLIProxyAPI · error
vertex credential: merge metadata failed: %w
Error message
vertex credential: merge metadata failed: %w
What it means
Returned by VertexCredentialStorage.SaveTokenToFile when misc.MergeMetadata fails to combine the storage struct with its Metadata map before JSON encoding (vertex_credentials.go:64-67). Like the Kimi equivalent, this is a JSON-marshal failure over the metadata — the VertexCredentialStorage or its Metadata contains values Go's encoder cannot serialize.
Source
Thrown at internal/auth/vertex/vertex_credentials.go:66
// It ensures the parent directory exists and logs the operation for transparency.
func (s *VertexCredentialStorage) SaveTokenToFile(authFilePath string) error {
misc.LogSavingCredentials(authFilePath)
if s == nil {
return fmt.Errorf("vertex credential: storage is nil")
}
if s.ServiceAccount == nil {
return fmt.Errorf("vertex credential: service account content is empty")
}
// Ensure we tag the file with the provider type.
s.Type = "vertex"
if err := os.MkdirAll(filepath.Dir(authFilePath), 0o700); err != nil {
return fmt.Errorf("vertex credential: create directory failed: %w", err)
}
data, errMerge := misc.MergeMetadata(s, s.Metadata)
if errMerge != nil {
return fmt.Errorf("vertex credential: merge metadata failed: %w", errMerge)
}
f, err := os.Create(authFilePath)
if err != nil {
return fmt.Errorf("vertex credential: create file failed: %w", err)
}
defer func() {
if errClose := f.Close(); errClose != nil {
log.Errorf("vertex credential: failed to close file: %v", errClose)
}
}()
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
if err = enc.Encode(data); err != nil {
return fmt.Errorf("vertex credential: encode failed: %w", err)
}
return nil
}View on GitHub (pinned to 78f0c4079e)
Solutions
- Restrict Metadata entries to JSON-native types; stringify anything exotic before assignment
- Inspect the wrapped cause in the error chain to find the offending key
- If ServiceAccount was built programmatically, ensure it came from json.Unmarshal rather than hand-built Go values
Example fix
// before
s.Metadata = map[string]any{"stop": make(chan struct{})}
// after
s.Metadata = map[string]any{"stop": "signal-name"} Defensive patterns
Strategy: validation
Validate before calling
if _, err := json.Marshal(s.Metadata); err != nil {
return fmt.Errorf("vertex metadata not serializable: %w", err)
} Try / catch
if err := s.SaveTokenToFile(path); err != nil && strings.Contains(err.Error(), "merge metadata failed") {
s.Metadata = nil
err = s.SaveTokenToFile(path)
} Prevention
- Store only JSON-native values in metadata maps
- Encode exotic values to strings at assignment time
- Test save with production-shaped metadata
When it happens
Trigger: Metadata map holding channels, funcs, or cyclic references; a ServiceAccount map containing unserializable Go values (rare, since it normally comes from JSON); unsupported numeric types like NaN.
Common situations: SDK embedders attaching runtime objects as metadata; NaN/Inf floats injected by custom accounting code; effectively unreachable via plain config-driven usage.
Related errors
- failed to merge metadata: %w
- invalid auth file: %w
- source auth path is empty
- invalid auth file: %w
- failed to merge metadata: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/154cde6698daa52d.
Report an issue: GitHub.