charmbracelet/crush · error

permission request failed: %w

Error message

permission request failed: %w

What it means

When an LSP rename targets a path outside the working directory, a permission request is created and submitted. If the permissions subsystem itself errors (store failure, context cancellation), the error is wrapped as 'permission request failed'. This is distinct from an explicit denial, which returns a permission-denied response instead.

Source

Thrown at internal/agent/tools/lsp_rename.go:71

			edit, err := resolved.client.Rename(ctx, resolved.path, resolved.line, resolved.char, params.NewName)
			if err != nil {
				slog.Error("Failed to rename symbol", "error", err, "symbol", params.Symbol)
				return fantasy.NewTextErrorResponse(fmt.Sprintf("rename failed: %s", err)), nil
			}
			if edit == nil {
				return fantasy.NewTextResponse(fmt.Sprintf("No rename edits generated for symbol '%s'", params.Symbol)), nil
			}

			sessionID := GetSessionFromContext(ctx)
			if sessionID != "" && permissions != nil {
				granted, err := permissions.Request(ctx, permission.CreatePermissionRequest{
					SessionID:   sessionID,
					ToolName:    RenameToolName,
					Description: fmt.Sprintf("Rename '%s' to '%s'", params.Symbol, params.NewName),
				})
				if err != nil {
					return fantasy.ToolResponse{}, fmt.Errorf("permission request failed: %w", err)
				}
				if !granted {
					return NewPermissionDeniedResponse(), nil
				}
			}

			affectedFiles := collectAffectedFiles(edit)

			if files != nil && sessionID != "" {
				for _, path := range affectedFiles {
					content, err := os.ReadFile(path)
					if err != nil {
						slog.Warn("Failed to read file for version tracking", "path", path, "error", err)
						continue
					}
					if _, err := files.CreateVersion(ctx, sessionID, path, string(content)); err != nil {
						slog.Warn("Failed to create file version", "path", path, "error", err)
					}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Inspect the wrapped %w error for the underlying cause.
  2. Ensure the SQLite database backing permissions is writable and not locked.
  3. Retry the rename; transient DB or context issues resolve on a fresh attempt.
  4. Keep the rename target inside the working directory to skip the permission path entirely.

Example fix

// before
Rename(ctx, params) // db locked -> permission request failed
// after
// ensure no other process holds the DB lock, then retry
Rename(ctx, params)
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure DB-backed permission store reachable before tool call
if err := permissions.Ping(ctx); err != nil { return err }

Type guard

null

Try / catch

_, err := renameTool(ctx, params)
if err != nil {
    if strings.Contains(err.Error(), "permission request failed") {
        // retry once after checking DB health / context cancellation
    }
}

Prevention

When it happens

Trigger: Invoking the LSP rename tool on an out-of-working-dir path while permissions.Request fails: DB (permission store) unavailable, context canceled mid-request, or a malformed session ID.

Common situations: Database locked or corrupted during permission persistence; user canceled the TUI prompt closing the context; running headless where the permission service isn't wired.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/3d6391f57c64aca4. Report an issue: GitHub.