fix(blocks): prevent TypeError when auto_credentials field is empty - #12588
fix(blocks): prevent TypeError when auto_credentials field is empty#12588ntindle wants to merge 2 commits into
Conversation
When a GoogleDriveFileField input (e.g. spreadsheet) is empty/None, the executor skips credential injection. The block's run() is then called without the required `credentials` kwarg, causing a TypeError wrapped as BlockUnknownError. Fix in two layers: - _base.py: inject None for missing auto_credentials kwargs in _execute() so all GoogleDriveFileField blocks get a clean fallback - GoogleSheetsReadBlock: accept optional credentials and guard against None Fixes OPEN-2895 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
WalkthroughThese changes add defensive handling for missing credentials in the block execution framework. The base Block class now ensures auto-credential kwargs are always present (defaulting to None), while GoogleSheetsReadBlock explicitly handles the case when credentials are not provided, yielding a clean error message rather than failing with a TypeError. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
|
||
| with pytest.raises(BlockExecutionError, match="No spreadsheet selected"): | ||
| async for _ in block.execute(input_data): | ||
| pass |
There was a problem hiding this comment.
🤖 🟡 Nice to Have: This test covers the spreadsheet=None path (line 331), but the new credentials=None guard (lines 337-338) is untested. Consider adding a second test case that provides a valid spreadsheet dict but no credentials to exercise that path too:
async def test_sheets_read_no_credentials_yields_clean_error():
block = GoogleSheetsReadBlock()
input_data = {
"spreadsheet": {
"id": "abc123",
"name": "Test",
"mimeType": "application/vnd.google-apps.spreadsheet",
},
"range": "Sheet1!A1:B2",
}
with pytest.raises(BlockExecutionError, match="Google credentials are required"):
async for _ in block.execute(input_data):
pass
majdyz
left a comment
There was a problem hiding this comment.
Clean, well-structured fix. The two-layer approach (systemic _base.py safety net + block-level guard) is the right call.
What I checked:
_base.py:setdefaultcorrectly injectsNoneonly for missing auto_credentials kwargs without overwriting already-resolved ones. Placement after input validation is correct.sheets.py: Optionalcredentialsparam + early guard yields clean user-facing error.- Test validates the TypeError→BlockExecutionError improvement.
- Verified all other Google Docs/Sheets blocks have early
if not input_data.document/spreadsheetguards, so the systemicNoneinjection won't cause regressions in the common empty-field case.
One nice-to-have inline comment about test coverage for the credentials=None path — not blocking.
Review: PR #12588Issue Found: Incomplete credentials guard for sibling Sheets blocksThe There are 19 other Google Sheets blocks (Write, Update, Delete, etc.) that still have: async def run(self, input_data: Input, *, credentials: GoogleCredentials, **kwargs)After this PR, those blocks will receive Recommendation: Either:
Option 2 is better because it provides a single centralized guard rather than requiring every block author to remember the pattern. CI NoteThe test failures (3.11, 3.12, 3.13) were actually CANCELLED due to the "Check PR Status" meta-check timing out -- not real test failures. The tests that did run all passed. A re-run should fix this. |
| # kwarg don't crash with TypeError when the execution context didn't | ||
| # resolve credentials (e.g. the GoogleDriveFile field was empty). | ||
| for kwarg_name in self.input_schema.get_auto_credentials_fields(): | ||
| kwargs.setdefault(kwarg_name, None) |
There was a problem hiding this comment.
🤖 🟠 Should Fix: The systemic setdefault(kwarg_name, None) injects None into the run() kwargs for all blocks using GoogleDriveFileField — there are 30+ such blocks in sheets.py and 18+ in docs.py. However, only GoogleSheetsReadBlock.run() was updated to accept credentials: GoogleCredentials | None = None with a guard.
For the remaining blocks, this means:
- If
spreadsheet/documentfield is empty, the earlyif not input_data.spreadsheetguard fires first, socredentials=Noneis harmless — this is fine. - But if a block receives a valid
spreadsheet/documentANDcredentials=None(which could happen if credential resolution silently fails or is skipped), the block will call_build_sheets_service(None)/_build_drive_service(None)→AttributeErroron None →BlockUnknownError. This is the exact same class of opaque error this PR aims to fix.
Since the _base.py change is systemic and touches all auto_credentials blocks, the type safety contract (credentials: GoogleCredentials — required, non-None) is now silently violated for all of them. The systemic fix and the block-level fix are at odds: the systemic fix guarantees None can be injected, but only one block has been updated to handle it.
Suggestion: Either:
- (A) Remove the systemic
_base.pychange entirely and instead guard in the executor/manager (where credentials are resolved) — soNonenever reachesrun()in the first place, OR - (B) Keep the systemic fix but add a second systemic guard: if any auto_credentials kwarg is still
Noneafter resolution, yield a clean error from_execute()before callingself.run(). This way individual blocks don't need to change at all.
Option (B) keeps this simple and avoids touching 50+ blocks:
for kwarg_name in self.input_schema.get_auto_credentials_fields():
kwargs.setdefault(kwarg_name, None)
if kwargs[kwarg_name] is None:
yield "error", f"Credentials required but not provided for '{kwarg_name}'"
return| credentials: GoogleCredentials | None = None, | ||
| **kwargs, | ||
| ) -> BlockOutput: | ||
| if not input_data.spreadsheet: |
There was a problem hiding this comment.
🤖 🟠 Should Fix: This block-level fix (making credentials optional + adding a guard) is correct in isolation, but it is inconsistent: there are 30+ other blocks in this file and 18+ in docs.py that have the exact same credentials: GoogleCredentials required kwarg pattern with GoogleDriveFileField.
After the _base.py systemic change, all of those blocks can now receive credentials=None. Only this one was updated to handle it. If the systemic fix is kept, either all blocks should be updated, or (better) the guard should be moved to _execute() in _base.py so no individual block needs to change.
As-is, this creates a maintenance trap: contributors will look at GoogleSheetsReadBlock as a pattern, see credentials: GoogleCredentials | None = None, but won't know they need to replicate this in every other block.
|
|
||
| with pytest.raises(BlockExecutionError, match="No spreadsheet selected"): | ||
| async for _ in block.execute(input_data): | ||
| pass |
There was a problem hiding this comment.
🤖 🟡 Nice to Have: The test uses block.execute() which goes through _execute() → run(). This is good because it exercises the full path including the new _base.py setdefault logic.
However, the test asserts BlockExecutionError with match="No spreadsheet selected" — this only exercises the pre-existing if not input_data.spreadsheet guard (line 331), NOT the new if not credentials guard (lines 337-338) added by this PR.
The new code path this PR adds (the credentials=None guard) is completely untested. Please add a test that provides a valid spreadsheet but no credentials to verify the new guard works:
async def test_sheets_read_no_credentials_yields_clean_error():
block = GoogleSheetsReadBlock()
input_data = {
"spreadsheet": {
"id": "abc123",
"name": "Test",
"mimeType": "application/vnd.google-apps.spreadsheet",
},
"range": "Sheet1!A1:B2",
}
with pytest.raises(BlockExecutionError, match="Google credentials are required"):
async for _ in block.execute(input_data):
pass(I see @majdyz already noted this — adding emphasis that this is the only test for the new code and it doesn't actually test it.)
majdyz
left a comment
There was a problem hiding this comment.
Review Summary
PR description quality: Excellent — clear Why/What/How structure, risk assessment, and checklist. Well done.
Correctness: The fix addresses the reported bug (TypeError when GoogleDriveFile field is empty), but introduces a new inconsistency.
Key findings:
🟠 Systemic fix vs. block-level fix mismatch (Should Fix)
The _base.py change injects credentials=None for all blocks using GoogleDriveFileField (50+ blocks across sheets.py and docs.py). But only GoogleSheetsReadBlock was updated to handle None credentials. This creates two problems:
- Type safety violation: All other blocks declare
credentials: GoogleCredentials(required, non-None) but can now silently receiveNoneat runtime. Pyright won't catch this because the injection happens via**kwargs. - Latent bug path: If a block receives a valid spreadsheet/document AND
Nonecredentials (edge case, but possible),_build_sheets_service(None)will throw an opaqueAttributeError— the exact class of error this PR aims to fix.
Recommended fix: Move the None guard into _execute() in _base.py so it's truly systemic. After kwargs.setdefault(kwarg_name, None), check if kwargs[kwarg_name] is None and yield a clean error. This way no individual block needs to change, and the type contract credentials: GoogleCredentials remains valid for all 50+ blocks.
🟡 Test doesn't exercise new code path (Nice to Have)
The single test only hits the pre-existing "No spreadsheet selected" guard. The new credentials=None guard added by this PR is untested. (If the systemic fix in _base.py is updated per recommendation, the block-level guard in sheets.py can be removed entirely, and the test should instead validate the systemic error message.)
Request
Please address the systemic inconsistency before merging. The two concrete options are in my inline comment on _base.py. After addressing, please show test output proving both paths (no spreadsheet, no credentials) yield clean errors.
|
@ntindle friendly ping -- the changes-requested items from my review on Mar 31 are still outstanding, and there have been no new commits since the merge from TL;DR of what needs to change (same as my earlier inline comments): The core issue is that the Recommended path forward (Option B from my inline comment): Move the None guard into for kwarg_name in self.input_schema.get_auto_credentials_fields():
kwargs.setdefault(kwarg_name, None)
if kwargs[kwarg_name] is None:
yield "error", f"Credentials required but not provided for '{kwarg_name}'"
returnWith this change:
Additionally, please add a test case that exercises the new Happy to help if you have questions on the approach. |
|
When the feedback is addressed, please re-request review so I can take another look. |
…2269) (Significant-Gravitas#12874) ### Why / What / How **Why:** A beta user spent significant time trying to build and run agents that read Google Sheets. Four separate failures compounded on their session — all already open in Linear as SECRT-2266 through SECRT-2269. Three in-flight PRs each addressed a piece but conflicted on the same files (`backend/data/model.py`, `backend/blocks/_base.py`, `autogpt_libs/.../types.py`), so landing them individually would have been churn. One of the four reported issues (the credential-delete crash) is also the top unresolved Sentry issue `AUTOGPT-SERVER-6HB` with 100+ events going back to 2025-10-20 — it was archived as "ignored" but is a real regression. Bug Significant-Gravitas#4 required new work; the others we got by adopting the existing open PRs and addressing a pending review comment. **What:** This PR consolidates the three in-flight PRs, adds the two pieces of new work needed to fully close the beta blockers, and addresses the pending review on one of the three PRs so it doesn't require a second round. - **Closes PR Significant-Gravitas#12004** — Google Drive auto-credentials handling (merged in) - **Closes PR Significant-Gravitas#12748** — Incremental OAuth for scope upgrades (merged in) - **Closes PR Significant-Gravitas#12588** — superseded by the systemic None-guard here (see "How" below) - **Adds Bug 2 fix** — Google credential deletion no longer crashes on `revoke_tokens` - **Adds Bug 4 validator** — the agent builder can no longer save a graph with a hardcoded Drive file ID **How:** 1. **Adopt PR Significant-Gravitas#12004 (Bug 1 — auto-credentials resolution).** Tags Drive-file fields as `is_auto_credential` on `CredentialsFieldInfo`, exposes `BlockSchema.get_auto_credentials_fields()` and `Graph.regular_credentials_inputs` / `auto_credentials_inputs`, extracts `_acquire_auto_credentials()` in the executor to resolve embedded `_credentials_id` at run time, clears `_credentials_id` on agent fork so cloned agents don't inherit the original author's credential, and fixes the Firefox referrer policy on the Google Drive picker script load. 2. **Adopt PR Significant-Gravitas#12748 (Bug 3 — credential accumulation).** OAuth callback now merges scopes into an existing credential (explicit via `credential_id` in OAuth state, or implicit via `provider + username` match) instead of appending a new row on every reconnect. GitHub's non-incremental OAuth path requests the union of existing + new scopes at login so the upgrade path works there too. 3. **Replace PR Significant-Gravitas#12588 with a systemic None-guard (addresses reviewer feedback).** The original PR added a per-block `credentials: GoogleCredentials | None = None` + early guard pattern that would need to be repeated across 50+ blocks with `GoogleDriveFileField`. Per the reviewer's ask, we moved the guard into `Block._execute()` once: after the `setdefault` loop, if `kwargs[kwarg_name] is None` we raise `BlockExecutionError` with a clean user-facing message. The per-block change in `sheets.py` is dropped so `credentials: GoogleCredentials` stays non-`Optional`. Dry-run path skips the guard (executor intentionally runs blocks without resolved creds for schema validation). 4. **Fix Bug 2 — Google revoke_tokens (SECRT-2267, AUTOGPT-SERVER-6HB).** `revoke_tokens()` was handing our Pydantic `OAuth2Credentials` into google-auth's `AuthorizedSession`, which calls `self.credentials.before_request(...)` on the object and crashes with `AttributeError: 'OAuth2Credentials' object has no attribute 'before_request'`. Google's token revoke endpoint doesn't need any auth header — just `token=<token>` in the form body per [Google's docs](https://developers.google.com/identity/protocols/oauth2/web-server#tokenrevoke). Switched to the platform's async `Requests` helper, matching how `reddit.py` / `github.py` / `todoist.py` / other providers do revocation. No google-auth objects involved. 5. **Fix Bug 4 — hardcoded Drive file IDs in agent graphs (SECRT-2269).** Evidence from the beta user's session: CoPilot's agent-builder produced 13 saved graph versions in one session where each one stuffed either a bare string (`"1KAv…"`) or a partial object (`{"id": "1KAv…"}`) into `GoogleSheetsReadBlock.constantInput.spreadsheet`, never wiring an `AgentGoogleDriveFileInputBlock` as the intended input. Bare-string versions failed pydantic validation with `is not of type 'object'`; object-with-only-`id` versions would have crashed at run time because `_acquire_auto_credentials` has no `_credentials_id` to resolve. Added a validator in `GraphModel._validate_graph_get_errors` that flags any auto-credentials field whose `input_default.<field>` is a bare string OR a dict missing `_credentials_id`, when there's no upstream link feeding the field. Remediation text is format-aware: when `field_schema["format"] == "google-drive-picker"` it names `AgentGoogleDriveFileInputBlock` specifically; for any other future auto-credentials format (OneDrive / Dropbox / etc.) the remediation is generic, so we don't ship a stale Google-specific hint that doesn't apply. A companion handoff for the CoPilot agent-builder team is drafted at `/tmp/agent-builder-ticket-drive-file-input.md` (to be filed in their tracker). The validator here is a safety net so reviewers and the LLM both get a clear error with the correct remediation; the agent-builder itself still needs to learn the correct pattern so it stops trying to hardcode Drive files in the first place. ### Changes 🏗️ **Backend** - `backend/data/model.py` — merged `is_auto_credential` + `input_field_name` (Significant-Gravitas#12004) with `OAuthState.credential_id` (Significant-Gravitas#12748); kept HEAD's defensive `set()` copy on `discriminator_values`. - `backend/blocks/_base.py` — `_execute()` runs the auto-credentials setdefault loop + raises `BlockExecutionError` when a resolved value is `None`. - `backend/blocks/google/sheets_test.py` — 2 new tests (systemic None-guard behaviour). - `backend/blocks/google/_drive.py`, `_drive_test.py` — unchanged on this branch (earlier bare-string validator was reverted after feedback; see "Out of scope" below). - `backend/data/graph.py` — auto-credentials anti-pattern validator in `_validate_graph_get_errors`. - `backend/data/graph_test.py` — 11 new tests for the validator. - `backend/integrations/oauth/google.py` — `revoke_tokens` swapped to `Requests().post`, removed `AuthorizedSession` misuse. - `backend/integrations/oauth/google_test.py` — 3 new tests covering the revoke happy path, no-access-token, and non-2xx-response. - `backend/integrations/credentials_store.py` — from Significant-Gravitas#12748. - `backend/api/features/integrations/router.py` — incremental-OAuth callback + scope upgrade helpers (from Significant-Gravitas#12748). - `backend/api/features/integrations/incremental_oauth_test.py` — 15 tests (from Significant-Gravitas#12748). - `backend/api/features/chat/tools/utils.py` → renamed to `backend/copilot/tools/utils.py` during merge; now uses `regular_credentials_inputs` for missing-creds + matching (from Significant-Gravitas#12004). - `backend/copilot/tools/utils_test.py` — moved from `api/features/chat/tools/`, import paths updated. - `backend/api/features/library/db.py` — library preset guard uses `regular_credentials_inputs` (from Significant-Gravitas#12004). - `backend/data/graph.py` — `regular_credentials_inputs` / `auto_credentials_inputs` properties + `_reassign_ids` clears `_credentials_id` on fork (from Significant-Gravitas#12004). - `backend/executor/manager.py` — `_acquire_auto_credentials()` extracted + validation (from Significant-Gravitas#12004). - `backend/executor/utils.py`, `utils_test.py`, `manager_auto_credentials_test.py` — auto-credentials tests (from Significant-Gravitas#12004). **Frontend** - `frontend/src/components/contextual/GoogleDrivePicker/helpers.ts` — Firefox referrer fix (from Significant-Gravitas#12004). - `frontend/src/components/contextual/CredentialsInput/useCredentialsInput.ts`, `src/hooks/useCredentials.ts`, `src/lib/autogpt-server-api/client.ts`, `src/providers/agent-credentials/credentials-provider.tsx`, `src/app/api/openapi.json` — incremental-OAuth scope upgrade UI (from Significant-Gravitas#12748). **Shared libs** - `autogpt_libs/supabase_integration_credentials_store/types.py` — merged additions from both Significant-Gravitas#12004 and Significant-Gravitas#12748. ### Test plan 📋 - [x] `poetry run lint` — clean - [x] `poetry run pytest backend/data/graph_test.py` — 55 passed including 11 new validator tests - [x] `poetry run pytest backend/integrations/oauth/google_test.py` — 3 new tests passing - [x] `poetry run pytest backend/blocks/google/sheets_test.py` — 2 new tests passing - [x] `poetry run pytest backend/blocks/google/ backend/integrations/oauth/ backend/executor/ backend/data/graph_test.py backend/api/features/integrations/ backend/copilot/tools/utils_test.py` — 250 passed, 6 pre-existing failures that require the docker stack (RabbitMQ/Redis/Postgres) and fail identically on `origin/dev` - [x] `pnpm format` — clean - [x] `pnpm lint` — 3 pre-existing `<img>` warnings on files I didn't touch, no errors - [x] `pnpm types` — pre-existing errors on `AgentActivityDropdown` that also fail on `origin/dev` (unrelated to this PR; needs a separate fix on dev) - [x] Live repro on dev verified Bug 2 fires against current prod code — two fresh Sentry events in `AUTOGPT-SERVER-6HB` at 2026-04-21T21:35:54Z on `app:dev-behave:cloud` matching the exact `DELETE /api/integrations/google/credentials/{cred_id}` path. Airtable OAuth2 delete as a control worked cleanly, confirming Google-specific. - [x] Live repro on dev verified Bug 4 (CoPilot direct-run variant) — `{"spreadsheet": {"id": "..."}}` → `Cannot use file 'None' (type: None)` from `_validate_spreadsheet_file` mimeType check, as expected. Reviewer post-merge verification: - [ ] Delete a Google OAuth credential via the Integrations UI — succeeds cleanly, no Sentry event fires - [ ] Connect Google twice (same account, same scopes) — credential count stays at 1 (dedup) - [ ] Save an agent graph with `GoogleSheetsReadBlock.constantInput.spreadsheet = "bare-id"` via API — graph validator rejects with `AgentGoogleDriveFileInputBlock` remediation - [ ] Save an agent graph with `GoogleSheetsReadBlock` whose `spreadsheet` is fed by an upstream `AgentGoogleDriveFileInputBlock.result` — validator accepts, agent runs ### Out of scope (for follow-ups) - **Bug 1 — "Failed to retrieve Google OAuth credentials"** in `frontend/src/components/contextual/GoogleDrivePicker/useGoogleDrivePicker.ts:163`. Zero hits for this string in the beta user's Langfuse traces and we weren't able to reproduce it from a clean flow. Most likely a stale-credential race condition (delete in another tab, picker queries a stale React-Query cache). Tracked as a separate task; not blocking. - **CoPilot first-attempt mimeType retry loop.** Observed on dev: CoPilot's first call to `GoogleSheetsReadBlock` sends `{"spreadsheet": {"id": "..."}}` without `mimeType`, hits `_validate_spreadsheet_file`, retries with mimeType. Costs a round-trip. Two possible fixes (relax `_validate_spreadsheet_file` to skip when mimeType is `None` and let Google's API surface the real error; OR extend `get_auto_credentials_fields` metadata so CoPilot's tool description prompts it to always include mimeType). Deliberately deferred — fixing only one of "API caller sends a bare string" or "CoPilot sends an incomplete object" risked the same auth-ambiguity the bare-string commit in this branch history hit. - **CoPilot agent-builder prompt/guide update.** The validator here produces the correct error message, but the agent-builder model still needs to learn to use `AgentGoogleDriveFileInputBlock` upfront rather than discover it through validator retries. Separate handoff ticket filed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches OAuth credential issuance/upgrade paths and introduces a new endpoint that returns raw access tokens (scope-gated), plus broad changes to execution-time credential resolution/validation; mistakes could impact auth/security or break integrations. > > **Overview** > Fixes several Google/Drive agent-builder blockers by **supporting incremental OAuth scope upgrades** and by hardening how credential-bearing file inputs (“auto-credentials”) are validated, resolved, and cleared on graph fork. > > On the integrations API, `/{provider}/login` now accepts `credential_id` and persists it in `OAuthState` to upgrade an existing OAuth2 credential on callback (explicit upgrade), with an implicit merge path for same `provider+username`. The callback path now merges scopes/metadata, preserves ID/title, preserves existing `refresh_token`/`username` when missing from incremental responses, blocks upgrades for managed/system credentials, and adds a **new `/{provider}/credentials/{cred_id}/picker-token` endpoint** to return a short-lived access token for provider-hosted pickers (currently allowlisted to Google Drive scopes). > > For auto-credentials, `CredentialsFieldInfo` gains `is_auto_credential` + `input_field_name`, graphs now expose `regular_credentials_inputs` vs `auto_credentials_inputs`, and multiple callers switch from `aggregate_credentials_inputs()` to `regular_credentials_inputs` so embedded picker credentials aren’t treated as user-mapped inputs. Execution-time auto-credential acquisition is extracted into `_acquire_auto_credentials()` with clearer error handling and lock cleanup; block execution adds a systemic guard to surface a clean `Missing credentials` error when auto-credentials are absent. > > Separately fixes Google credential deletion by rewriting `GoogleOAuthHandler.revoke_tokens()` to use the platform `Requests` helper (bounded retries) instead of `AuthorizedSession`, and expands test coverage across these flows (incremental OAuth, picker-token, auto-credential validation/acquisition, graph validator, and frontend diagnostics test stubs). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cac36ea. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Why / What / How
Why:
GoogleSheetsReadBlockcrashes withBlockUnknownErrorwrapping aTypeError: missing 1 required keyword-only argument: 'credentials'when the block is executed without a spreadsheet selected. Instead of a clean user-facing error, users see an opaque internal error.What: Fix the auto_credentials injection path so blocks using
GoogleDriveFileFielddon't crash when their file input is empty.How: Two-layer fix:
_base.py): In_execute(), injectNonefor any auto_credentials kwargs not already present inkwargsviasetdefault. This preventsTypeErrorfor all blocks usingGoogleDriveFileField.sheets.py): MakeGoogleSheetsReadBlock.run()acceptcredentials: GoogleCredentials | None = Noneand add a guard that yields a clean error when credentials are missing.Changes 🏗️
backend/blocks/_base.py: Added auto_credentials kwargs defaulting in_execute()before callingself.run()backend/blocks/google/sheets.py: MadeGoogleSheetsReadBlock.run()credentials parameter optional with a None guardbackend/blocks/google/sheets_test.py: New test verifying clean error instead of TypeErrorChecklist 📋
For code changes:
test_sheets_read_no_spreadsheet_yields_clean_errorpassestest_available_blocks[GoogleSheetsReadBlock]still passespoetry run formatandpoetry run lintcleanpyrightreports 0 errors on changed filesNote
Medium Risk
Touches the core block execution path by injecting default
Nonevalues for auto-credential kwargs, which could subtly affect any block relying on kwargs presence/absence. Behavior change is guarded and includes a targeted Google Sheets regression test, but warrants review across other auto-credentialed blocks.Overview
Prevents blocks that use auto-resolved credentials (e.g. via
GoogleDriveFileField) from crashing with aTypeErrorwhen the related input is empty by defaulting any missing auto-credentials kwargs toNoneinBlock._execute().Updates
GoogleSheetsReadBlockto accept optionalcredentialsand emit a clean user-facing error when credentials are missing, and adds a regression test ensuring executing without a spreadsheet yieldsBlockExecutionErrorrather than an unknown/internal error.Written by Cursor Bugbot for commit 001ef93. This will update automatically on new commits. Configure here.