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).

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)

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.