github/copilot-sdk · error

SessionFS.InitialWorkingDirectory is required

Error message

SessionFS.InitialWorkingDirectory is required

What it means

NewClient calls validateSessionFSConfig when a SessionFSConfig is supplied. SessionFS requires at minimum an initial working directory; if InitialWorkingDirectory is empty this error is returned before the client is created. SessionStatePath and Conventions are validated immediately after.

Solutions

  1. Set InitialWorkingDirectory to an absolute path of an existing directory before calling NewClient.
  2. Populate it from an env var with a fallback and fail fast with a clearer message if empty.
  3. Verify the other required fields too: SessionStatePath (non-empty) and Conventions (SessionFSSetProviderConventionsPosix or Windows).

Example fix

// before
client, err := NewClient(ctx, ClientOptions{
    SessionFS: &SessionFSConfig{Conventions: rpc.SessionFSSetProviderConventionsPosix},
})
// after
client, err := NewClient(ctx, ClientOptions{
    SessionFS: &SessionFSConfig{
        InitialWorkingDirectory: "/home/user/project",
        SessionStatePath:        "/home/user/.copilot/session-state",
        Conventions:             rpc.SessionFSSetProviderConventionsPosix,
    },
})
Defensive patterns

Strategy: validation

Validate before calling

func validateFS(cfg *SessionFSConfig) error {
    if cfg == nil { return nil }
    if cfg.InitialWorkingDirectory == "" { return errors.New("InitialWorkingDirectory must be set") }
    if cfg.SessionStatePath == "" { return errors.New("SessionStatePath must be set") }
    return nil
}

Try / catch

client, err := NewClient(ctx, opts)
if err != nil {
    if strings.Contains(err.Error(), "SessionFS.") {
        return fmt.Errorf("invalid SessionFS config: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Passing &SessionFSConfig{} (or SessionFSConfig with InitialWorkingDirectory unset) in ClientOptions to NewClient, while leaving InitialWorkingDirectory as the empty string zero value.

Common situations: Constructing the config from environment variables or flags where the path is unset/empty; struct literal initialization that sets SessionStatePath and Conventions but forgets InitialWorkingDirectory; copy-pasting a config and deleting the working directory field.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/5b4269665259aae3. Report an issue: GitHub.

Appendix: source

Thrown at go/client.go:87

		callbacks[defaultBearerTokenProviderName] = provider.BearerTokenProvider
	}
	for i := range providers {
		if providers[i].BearerTokenProvider != nil {
			callbacks[providers[i].Name] = providers[i].BearerTokenProvider
		}
	}
	if len(callbacks) == 0 {
		return nil
	}
	return callbacks
}

func validateSessionFSConfig(config *SessionFSConfig) error {
	if config == nil {
		return nil
	}
	if config.InitialWorkingDirectory == "" {
		return errors.New("SessionFS.InitialWorkingDirectory is required")
	}
	if config.SessionStatePath == "" {
		return errors.New("SessionFS.SessionStatePath is required")
	}
	if config.Conventions != rpc.SessionFSSetProviderConventionsPosix && config.Conventions != rpc.SessionFSSetProviderConventionsWindows {
		return errors.New("SessionFS.Conventions must be either 'posix' or 'windows'")
	}
	return nil
}

// validateEnvironmentOptions enforces the transport-specific rules for
// per-client environment, working directory, and telemetry. It panics (fails
// loud) on a misconfiguration, matching the other SDKs.
//
// The in-process transport loads the native runtime into this process, whose
// single environment block and process-global working directory cannot carry
// per-client values, and whose telemetry lowers to shared process-global env
// vars — so options that depend on them are rejected there. Child-process

View on GitHub (pinned to cd8cf15dc3)