temporalio/temporal · error
history was mutated
Error message
history was mutated
What it means
This is a wrapping error: validateCAs failed while checking the ServerTLS.ClientCAFiles entries. Each element must be a non-empty string naming a CA bundle file used to verify client certificates in mTLS. The wrapped error is almost always an empty-string entry.
Source
Thrown at common/archiver/constants.go:31
ArchiveSkippedInfoMsg = "Archive method encountered not found error and skipped the archival"
// ErrReasonInvalidURI is the error reason for invalid URI
ErrReasonInvalidURI = "URI is invalid"
// ErrReasonInvalidArchiveRequest is the error reason for invalid archive request
ErrReasonInvalidArchiveRequest = "archive request is invalid"
// ErrReasonReadHistory is the error reason for failing to read history
ErrReasonReadHistory = "failed to read history batches"
// ErrReasonHistoryMutated is the error reason for mutated history
ErrReasonHistoryMutated = "history was mutated"
)
var (
// ErrInvalidURI is the error for invalid URI
ErrInvalidURI = errors.New("URI is invalid")
// ErrURISchemeMismatch is the error for mismatch between URI scheme and archiver
ErrURISchemeMismatch = errors.New("URI scheme does not match the archiver")
// ErrHistoryMutated is the error for mutated history
ErrHistoryMutated = errors.New("history was mutated")
// ErrInvalidGetHistoryRequest is the error for invalid GetHistory request
ErrInvalidGetHistoryRequest = errors.New("get archived history request is invalid")
// ErrInvalidQueryVisibilityRequest is the error for invalid Query Visibility request
ErrInvalidQueryVisibilityRequest = errors.New("query visiblity request is invalid")
// ErrNextPageTokenCorrupted is the error for corrupted GetHistory token
ErrNextPageTokenCorrupted = errors.New("next page token is corrupted")
// ErrHistoryNotExist is the error for non-exist history
ErrHistoryNotExist = errors.New("requested workflow history does not exist")
)
View on GitHub (pinned to bde624efd1)
Solutions
- Remove empty strings from the ClientCAFiles list.
- If no client CAs are needed, set ClientCAFiles to an empty list instead of [""].
- Fix the templating/values logic that inserts the empty path.
- Verify each listed file exists and contains valid PEM CA certificates.
Example fix
// before ClientCAFiles: ["/etc/temporal/ca.pem", ""] // after ClientCAFiles: ["/etc/temporal/ca.pem"]
Defensive patterns
Strategy: validation
Validate before calling
for i, f := range cfg.ClientCAFiles {
if strings.TrimSpace(f) == "" {
return fmt.Errorf("ClientCAFiles[%d] is empty", i)
}
} Prevention
- Use empty lists ([]) instead of lists containing empty strings.
- Helm/Kustomize: use defaulting/trimming so optional CA paths render as [] not [""].
- Verify each CA file path exists in the container image or mounted volume.
When it happens
Trigger: Calling validateGroupTLS/validateServerTLS with ServerTLS.ClientCAFiles containing an empty or whitespace-only path string.
Common situations: A Helm/K8s values merge leaving an empty list element; a config snippet like client_ca_files: [""]; automated tooling appending an empty path when no extra CA is needed.
Related errors
- URI scheme does not match the archiver
- query visiblity request is invalid
- next page token is corrupted
- invalid operation token
- URI is invalid
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/775dd39e6959a799.
Report an issue: GitHub.