sipeed/picoclaw · error

invalid integer value: %s

Error message

invalid integer value: %s

What it means

Produced by parseFlexibleInt (pkg/auth/oauth.go:339) while decoding the interval field of the device-code response. The code first tries json.Unmarshal into int, then into string (accepting numeric strings); if both fail it rejects the value with 'invalid integer value: %s'. This means the JSON value is neither an integer nor a string — it is a float (e.g. 5.5), boolean, object, or array.

Source

Thrown at pkg/auth/oauth.go:339

	if len(raw) == 0 || string(raw) == "null" {
		return 0, nil
	}

	var interval int
	if err := json.Unmarshal(raw, &interval); err == nil {
		return interval, nil
	}

	var intervalStr string
	if err := json.Unmarshal(raw, &intervalStr); err == nil {
		intervalStr = strings.TrimSpace(intervalStr)
		if intervalStr == "" {
			return 0, nil
		}
		return strconv.Atoi(intervalStr)
	}

	return 0, fmt.Errorf("invalid integer value: %s", string(raw))
}

func LoginDeviceCode(cfg OAuthProviderConfig) (*AuthCredential, error) {
	reqBody, _ := json.Marshal(map[string]string{
		"client_id": cfg.ClientID,
	})

	resp, err := http.Post(
		cfg.Issuer+"/api/accounts/deviceauth/usercode",
		"application/json",
		strings.NewReader(string(reqBody)),
	)
	if err != nil {
		return nil, fmt.Errorf("requesting device code: %w", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Inspect the live response and confirm the JSON type of interval
  2. Fix the server/test fixture to emit an integer ("interval": 5) or a numeric string ("interval": "5")
  3. If fractional intervals are legitimate, extend parseFlexibleInt to unmarshal into float64 and truncate/round to int seconds

Example fix

// before (in parseFlexibleInt)
return 0, fmt.Errorf("invalid integer value: %s", string(raw))

// after (accept fractional seconds)
var intervalFloat float64
if err := json.Unmarshal(raw, &intervalFloat); err == nil {
	return int(intervalFloat), nil
}
return 0, fmt.Errorf("invalid integer value: %s", string(raw))
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check the interval field's JSON type before relying on the parse
var probe struct {
	Interval json.RawMessage `json:"interval"`
}
if err := json.Unmarshal(body, &probe); err == nil {
	if len(probe.Interval) > 0 {
		var f float64
		var s string
		if json.Unmarshal(probe.Interval, &f) == nil || json.Unmarshal(probe.Interval, &s) == nil {
			// number or string: parseFlexibleInt will accept it
		}
	}
}

Type guard

func isInvalidIntervalError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "invalid integer value")
}

Try / catch

if _, err := auth.RequestDeviceCode(cfg); err != nil {
	if isInvalidIntervalError(err) {
		// server contract changed: interval is neither number nor string
		return fmt.Errorf("provider interval field has unsupported type: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: The deviceauth/usercode response contains "interval": 5.5, "interval": true, "interval": {}, or "interval": []. Note: a non-numeric string like "abc" instead surfaces a strconv.Atoi error, and null/missing/empty-string interval are accepted as 0.

Common situations: Provider starts returning a fractional polling interval or switches interval to an object like {"seconds":5}; an API gateway rewriting the payload; a mocked/stubbed test server emitting JSON typed differently from production.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/d47275c2f3cd5a3c. Report an issue: GitHub.