crowdsecurity/crowdsec · error

unable to parse time

Error message

unable to parse time

What it means

ParseTimeFail is a sentinel error meaning an RFC3339 timestamp string could not be parsed by time.Parse. In crowdsec it surfaces when alert start_at/stop_at fields submitted to CreateAlert lack the RFC3339 format (e.g. missing timezone offset).

Solutions

  1. Format timestamps with time.RFC3339 (time.Now().Format(time.RFC3339)) before submitting.
  2. Ensure the string uses 'T' separator and an explicit offset/Z: convert with time.Parse then re-format.
  3. If ingesting third-party JSON, normalize the date field before calling the client API.
  4. Log the offending value (already included in the wrapped error) and correct the producer.

Example fix

// before
alert.StartAt = ptr("2024-05-01 12:00:00")
// after
alert.StartAt = ptr(time.Now().UTC().Format(time.RFC3339))
Defensive patterns

Strategy: validation

Validate before calling

func validRFC3339(s string) bool {
    _, err := time.Parse(time.RFC3339, s)
    return err == nil
}
// call before submitting: validRFC3339(alert.StartAt)

Try / catch

if _, _, _, err := client.CreateAlert(ctx, alert); err != nil {
    if errors.Is(err, database.ParseTimeFail) {
        return fmt.Errorf("fix start_at/stop_at to RFC3339: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: CreateAlert (via UpdateCommunityBlocklist or alert ingestion) when alertItem.StartAt or alertItem.StopAt is not a valid RFC3339 string, e.g. "2024-01-01 10:00:00" instead of "2024-01-01T10:00:00Z".

Common situations: Custom automation or bouncers posting alerts with locally formatted dates, hand-written JSON payloads without the 'T' separator or timezone, clients in non-UTC environments dropping the offset.

Understand the failure class

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/7c3ab65ff1c2d33a. Report an issue: GitHub.

Appendix: source

Thrown at pkg/database/errors.go:14

package database

import "errors"

var (
	UserExists        = errors.New("user already exist")
	UserNotExists     = errors.New("user doesn't exist")
	HashError         = errors.New("unable to hash")
	InsertFail        = errors.New("unable to insert row")
	QueryFail         = errors.New("unable to query")
	UpdateFail        = errors.New("unable to update")
	DeleteFail        = errors.New("unable to delete")
	ItemNotFound      = errors.New("object not found")
	ParseTimeFail     = errors.New("unable to parse time")
	ParseDurationFail = errors.New("unable to parse duration")
	MarshalFail       = errors.New("unable to serialize")
	BulkError         = errors.New("unable to insert bulk")
	ParseType         = errors.New("unable to parse type")
	InvalidIPOrRange  = errors.New("invalid ip address / range")
	InvalidFilter     = errors.New("invalid filter")
)

View on GitHub (pinned to 909b515798)