pulumi/pulumi · error

unable to unmarshal WhoAmIDetailedInfo: %w

Error message

unable to unmarshal WhoAmIDetailedInfo: %w

What it means

Thrown by LocalWorkspace.WhoAmIDetails when `pulumi whoami --json` succeeds but its stdout cannot be unmarshaled into WhoAmIResult. Means the CLI produced non-JSON or schema-incompatible output — typically a CLI older/newer than the struct expects, or extra text polluting stdout.

Source

Thrown at sdk/go/auto/local_workspace.go:560

		return "", newAutoError(fmt.Errorf("could not determine authenticated user: %w", err), stdout, stderr, errCode)
	}
	return strings.TrimSpace(stdout), nil
}

// WhoAmIDetails returns detailed information about the currently
// logged-in Pulumi identity.
func (l *LocalWorkspace) WhoAmIDetails(ctx context.Context) (WhoAmIResult, error) {
	// 3.58 added the --json flag (https://github.com/pulumi/pulumi/releases/tag/v3.58.0)
	if l.pulumiCommand.Version().GTE(semver.Version{Major: 3, Minor: 58}) {
		var whoAmIDetailedInfo WhoAmIResult
		stdout, stderr, errCode, err := l.runPulumiCmdSync(ctx, "whoami", "--json")
		if err != nil {
			return whoAmIDetailedInfo, newAutoError(
				fmt.Errorf("could not retrieve WhoAmIDetailedInfo: %w", err), stdout, stderr, errCode)
		}
		err = json.Unmarshal([]byte(stdout), &whoAmIDetailedInfo)
		if err != nil {
			return whoAmIDetailedInfo, fmt.Errorf("unable to unmarshal WhoAmIDetailedInfo: %w", err)
		}
		return whoAmIDetailedInfo, nil
	}

	stdout, stderr, errCode, err := l.runPulumiCmdSync(ctx, "whoami")
	if err != nil {
		return WhoAmIResult{}, newAutoError(
			fmt.Errorf("could not determine authenticated user: %w", err), stdout, stderr, errCode)
	}
	return WhoAmIResult{User: strings.TrimSpace(stdout)}, nil
}

// OrgGetDefault returns the default organization for the current backend.
func (l *LocalWorkspace) OrgGetDefault(ctx context.Context) (string, error) {
	bo := l.cliBaseOptions()
	result, err := l.cliAPI.OrgGetDefault(ctx, func(o *optorggetdefault.Options) {
		o.Cwd = bo.Cwd
		o.AdditionalEnv = bo.AdditionalEnv

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Pin/upgrade the workspace's PulumiCommand to a CLI version whose whoami --json schema matches the SDK's WhoAmIResult
  2. Inspect the raw stdout captured in the error context and remove any non-JSON pollution (banners, exec wrappers)
  3. Use WhoAmI(ctx) for just the username if full details are optional
  4. Wrap with errors.As/Unwrap to log the json.Unmarshal detail and the CLI version for bug reports

Example fix

// before
info, err := ws.WhoAmIDetails(ctx) // breaks with mismatched CLI
// after
v := ws.PulumiCommand.Version()
if v.LT(semver.Version{Major: 3, Minor: 130}) {
    return fmt.Errorf("upgrade pulumi CLI for compatible whoami --json output")
}
info, err := ws.WhoAmIDetails(ctx)
Defensive patterns

Strategy: fallback

Validate before calling

v := ws.PulumiCommand.Version()
if v.GTE(semver.Version{Major: 3, Minor: 58}) && v.LT(semver.Version{Major: 3, Minor: 999}) {
    // known-compatible band for whoami --json parsing
    _ = v
}

Type guard

func isJSONOutput(s string) bool {
    return strings.HasPrefix(strings.TrimSpace(s), "{")
}

Try / catch

info, err := ws.WhoAmIDetails(ctx)
if err != nil && strings.Contains(err.Error(), "unmarshal") {
    if user, uErr := ws.WhoAmI(ctx); uErr == nil {
        info = auto.WhoAmIResult{User: user} // degrade gracefully
    } else {
        return err
    }
} else if err != nil {
    return err
}

Prevention

When it happens

Trigger: Calling WhoAmIDetails with a CLI >= 3.58.0 whose whoami --json output schema differs from WhoAmIResult (orgs/types added or renamed in later versions); stdout polluted by login prompts or update notices.

Common situations: Very new CLIs adding fields handled fine, but breaking renames break parsing; old bundled CLIs emitting plain text despite the flag; wrapper scripts printing banners before JSON.

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/22d2f9cf2a9d33ac. Report an issue: GitHub.