pulumi/pulumi · error

listing audit logs: %w

Error message

listing audit logs: %w

What it means

This error is returned by Client.ListAuditLogs when the GET /api/orgs/{orgName}/auditlogs REST call fails. It wraps the underlying restCall error so the caller can see both the operation and the cause (auth, permissions, bad query params, network). Empty ListAuditLogsOptions fields are simply omitted from the query string, so malformed dates/tokens are the main client-side causes.

Source

Thrown at pkg/backend/httpstate/client/client.go:1741

func (pc *Client) ListAuditLogs(
	ctx context.Context, orgName string, opts ListAuditLogsOptions,
) (apitype.ListAuditLogEventsResponse, error) {
	queryObj := struct {
		EventType         string `url:"eventType,omitempty"`
		User              string `url:"user,omitempty"`
		StartTime         string `url:"startTime,omitempty"`
		ContinuationToken string `url:"continuationToken,omitempty"`
	}{
		EventType:         opts.EventType,
		User:              opts.User,
		StartTime:         opts.StartTime,
		ContinuationToken: opts.ContinuationToken,
	}

	var resp apitype.ListAuditLogEventsResponse
	path := fmt.Sprintf("/api/orgs/%s/auditlogs", url.PathEscape(orgName))
	if err := pc.restCall(ctx, http.MethodGet, path, queryObj, nil, &resp); err != nil {
		return resp, fmt.Errorf("listing audit logs: %w", err)
	}
	return resp, nil
}

// ExportAuditLogsOptions are the optional query parameters accepted by
// ExportAuditLogs. Empty fields are omitted from the request and let the
// service apply its own defaults.
type ExportAuditLogsOptions struct {
	// Format is the export format: "csv" or "cef". Empty defaults to "csv".
	Format string
	// EventType filters the audit log to a single event type. Empty means no
	// filter.
	EventType string
	// User filters the audit log to events triggered by a single user, by
	// GitHub login. Empty means no filter.
	User string
	// StartTime is the upper-bound timestamp of the time range to query, as
	// understood by the V1 endpoint. Empty means the service default.

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Verify PULUMI_ACCESS_TOKEN belongs to a user/role with audit log visibility (typically org Admin).
  2. Check the org name matches the Pulumi Cloud slug and ListAuditLogsOptions dates/tokens are correctly formatted.
  3. Clear the ContinuationToken and re-run from the first page if pagination broke.
  4. Retry on transient errors; inspect the wrapped error for the HTTP status code.

Example fix

// before
resp, err := client.ListAuditLogs(ctx, orgName, opts)
if err != nil { panic(err) }
// after
resp, err := client.ListAuditLogs(ctx, orgName, opts)
if err != nil {
    return fmt.Errorf("cannot read audit logs for %q: %w", orgName, err)
}
Defensive patterns

Strategy: validation

Validate before calling

if orgName == "" {
    return errors.New("organization name is required")
}
if opts.StartTime != "" || opts.EndTime != "" {
    // service expects RFC3339-style timestamps; validate format
    for _, t := range []string{opts.StartTime, opts.EndTime} {
        if t == "" { continue }
        if _, err := time.Parse(time.RFC3339, t); err != nil {
            return fmt.Errorf("invalid audit log timestamp %q: %w", t, err)
        }
    }
}

Type guard

func canReadAuditLogs(ctx context.Context, c *client.Client, org string) bool {
    _, err := c.ListAuditLogs(ctx, org, apitype.ListAuditLogsOptions{})
    var restErr *apitype.ErrorResponse
    return err == nil || (errors.As(err, &restErr) && restErr.Code != 403)
}

Try / catch

resp, err := client.ListAuditLogs(ctx, orgName, opts)
var restErr *apitype.ErrorResponse
if errors.As(err, &restErr) {
    switch restErr.Code {
    case 401, 403:
        return fmt.Errorf("audit log access denied for %q: %w", orgName, err)
    case 404:
        return fmt.Errorf("organization %q not found", orgName)
    }
}
if err != nil {
    return fmt.Errorf("listing audit logs: %w", err) // transient: retry
}

Prevention

When it happens

Trigger: Calling ListAuditLogs(ctx, orgName, opts) when the GET request fails: invalid or expired token (401), insufficient permissions to view audit logs (403), unknown org (404), malformed start/end dates or continuation token, or network failure.

Common situations: Audit-export scripts run with a token from a service account lacking audit-log read permission; date ranges with wrong format; org renamed so the slug no longer matches.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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