zoobzio January 23, 2026 Edit this page

Types Reference

Error Types

FieldError

type FieldError struct {
    Field string
    Err   error
}

Wraps an error with field context.

Fields:

  • Field — the struct field name where the error occurred
  • Err — the underlying error

Methods:

func (e *FieldError) Error() string
func (e *FieldError) Unwrap() error

Usage:

err := fig.Load(&cfg)
if err != nil {
    var fieldErr *fig.FieldError
    if errors.As(err, &fieldErr) {
        fmt.Printf("Field: %s\n", fieldErr.Field)
        fmt.Printf("Cause: %v\n", fieldErr.Err)
    }
}

Example Output:

fig: field Password: fig: required field not set

Sentinel Errors

ErrRequired

var ErrRequired = errors.New("fig: required field not set")

Returned when a field marked required:"true" has no value from any source.

Wrapped in: FieldError

Check:

if errors.Is(err, fig.ErrRequired) {
    // Handle missing required field
}

ErrInvalidType

var ErrInvalidType = errors.New("fig: invalid type conversion")

Returned when a string value cannot be converted to the target type.

Wrapped in: FieldError

Common causes:

  • Non-numeric string for int/float fields
  • Invalid boolean string (not true, false, 1, 0, etc.)
  • Invalid duration format
  • Unsupported target type

Check:

if errors.Is(err, fig.ErrInvalidType) {
    // Handle type conversion failure
}

ErrNotStruct

var ErrNotStruct = errors.New("fig: type must be a struct")

Returned when Load is called with a non-struct type.

Not wrapped: Returned directly from Load.

Example:

var s string
err := fig.Load(&s)  // Returns ErrNotStruct

ErrSecretNotFound

var ErrSecretNotFound = errors.New("fig: secret not found")

Returned by secret providers when a secret doesn't exist.

Behaviour: When a provider returns this error, fig continues to the next source (env, then default). It only becomes a Load error if the field is required and no other source provides a value.

For provider implementers: Return this error only for missing secrets. Return other errors for network issues, permission denied, etc.


Supported Types

fig converts string values to these types:

TypeParsingExample
stringDirect assignment"hello"
intstrconv.ParseInt"42"
int8strconv.ParseInt, converted to target"-128" to "127"
int16strconv.ParseInt, converted to target"-32768" to "32767"
int32strconv.ParseInt, converted to target"-2147483648" to "2147483647"
int64strconv.ParseInt"9223372036854775807"
uintstrconv.ParseUint"42"
uint8strconv.ParseUint, converted to target"0" to "255"
uint16strconv.ParseUint, converted to target"0" to "65535"
uint32strconv.ParseUint, converted to target"0" to "4294967295"
uint64strconv.ParseUint"18446744073709551615"
float32strconv.ParseFloat"3.14"
float64strconv.ParseFloat"3.141592653589793"
boolstrconv.ParseBool"true", "false", "1", "0"
time.Durationtime.ParseDuration"30s", "5m", "1h30m"
[]stringComma-separated split"a,b,c"["a", "b", "c"]
*TPointer to any supported typeSame as T
encoding.TextUnmarshalerUnmarshalText methodCustom types

Boolean Values

Accepted values for bool fields:

TrueFalse
truefalse
TRUEFALSE
TrueFalse
10
tf
TF

Duration Format

Duration strings use Go's time.ParseDuration format:

UnitSuffix
Nanosecondsns
Microsecondsus or µs
Millisecondsms
Secondss
Minutesm
Hoursh

Examples: "100ms", "30s", "5m", "1h30m", "2h45m30s"

String Slices

Comma-separated values are split and trimmed:

Tags []string `env:"TAGS"`  // TAGS="api, v2, prod" → ["api", "v2", "prod"]

Empty parts are removed: "a,,b"["a", "b"]

TextUnmarshaler

Types implementing encoding.TextUnmarshaler are supported:

type LogLevel int

func (l *LogLevel) UnmarshalText(text []byte) error {
    switch string(text) {
    case "debug":
        *l = 0
    case "info":
        *l = 1
    case "warn":
        *l = 2
    case "error":
        *l = 3
    default:
        return fmt.Errorf("unknown log level: %s", text)
    }
    return nil
}

type Config struct {
    Level LogLevel `env:"LOG_LEVEL" default:"info"`
}

Pointer Types

Pointers to supported types are handled automatically:

type Config struct {
    Port    *int    `env:"PORT"`           // nil if unset
    Host    *string `env:"HOST"`           // nil if unset
    Timeout *time.Duration `env:"TIMEOUT"` // nil if unset
}

Use pointers to distinguish between "unset" and "zero value".


Unsupported Types

The following types return ErrInvalidType:

  • Maps (map[K]V)
  • Slices other than []string
  • Channels
  • Functions
  • Complex numbers
  • Interfaces (except encoding.TextUnmarshaler)

For complex types, consider JSON encoding:

type Config struct {
    SettingsJSON string `env:"SETTINGS"`
}

func (c *Config) Settings() (map[string]any, error) {
    var m map[string]any
    return m, json.Unmarshal([]byte(c.SettingsJSON), &m)
}

Next Steps