netbirdio/netbird · error

parse service params %s: %w

Error message

parse service params %s: %w

What it means

service.json exists but json.Unmarshal rejected it as a serviceParams document, so the file is truncated/corrupted or shaped differently than the schema expects (for example a field stored as the wrong JSON type).

Source

Thrown at client/cmd/service_params.go:59

	return filepath.Join(configs.StateDir, serviceParamsFile)
}

// loadServiceParams reads saved service parameters from disk.
// Returns nil with no error if the file does not exist.
func loadServiceParams() (*serviceParams, error) {
	path := serviceParamsPath()

	data, err := os.ReadFile(path)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil //nolint:nilnil
		}
		return nil, fmt.Errorf("read service params %s: %w", path, err)
	}

	var params serviceParams
	if err := json.Unmarshal(data, &params); err != nil {
		return nil, fmt.Errorf("parse service params %s: %w", path, err)
	}

	return &params, nil
}

// saveServiceParams writes current service parameters to disk atomically
// with restricted permissions.
func saveServiceParams(params *serviceParams) error {
	path := serviceParamsPath()
	if err := util.WriteJsonWithRestrictedPermission(context.Background(), path, params); err != nil {
		return fmt.Errorf("save service params: %w", err)
	}
	return nil
}

// currentServiceParams captures the current state of all package-level
// variables into a serviceParams struct.
func currentServiceParams() *serviceParams {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Run netbird service reset-params to delete the bad file; the next install uses defaults
  2. Or fix the JSON syntax / restore from backup
  3. Pass settings explicitly on the next install (--log-level etc.) so the file is rewritten cleanly
  4. If it recurs, ensure two installs never run concurrently and check disk health

Example fix

# after a parse failure, discard and rebuild
netbird service reset-params
netbird service install --log-level debug
Defensive patterns

Strategy: fallback

Validate before calling

if data, err := os.ReadFile(serviceParamsPath()); err == nil {
	var probe serviceParams
	if jerr := json.Unmarshal(data, &probe); jerr != nil {
		_ = os.Rename(serviceParamsPath(), serviceParamsPath()+".corrupt")
		// proceed with defaults
	}
}

Type guard

func isCorruptParamsJSON(err error) bool {
	var syn *json.SyntaxError
	var typ *json.UnmarshalTypeError
	return errors.As(err, &syn) || errors.As(err, &typ)
}

Try / catch

if err := json.Unmarshal(data, &params); err != nil {
	if isCorruptParamsJSON(err) {
		_ = os.Remove(path) // or rename to .corrupt; defaults are re-derived on next install
		return nil, nil
	}
	return fmt.Errorf("parse service params %s: %w", path, err)
}

Prevention

When it happens

Trigger: A crash or kill during an older non-atomic write left a partial file; manual editing introduced a syntax error; a version change altered a field type (log_files expected as array).

Common situations: Power loss or forced reboot mid-install; hand-editing service.json to tweak the log level; downgrading the CLI over a newer service.json.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/1a34c834769fb37a. Report an issue: GitHub.