From f4f81bc4fc3237c04e4efa9b5fe6cc3156385b68 Mon Sep 17 00:00:00 2001 From: Nicholas Tindle Date: Fri, 6 Feb 2026 17:34:16 -0600 Subject: [PATCH] fix(backend): Remove _credentials_id key on fork instead of setting to None MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting _credentials_id to None on fork was ambiguous — both "forked, needs re-auth" and "chained data from upstream" were represented as None. This caused _acquire_auto_credentials to silently skip credential acquisition for forked agents, leading to confusing TypeErrors at runtime. Now the key is deleted entirely, making the three states unambiguous: - Present with value: user-selected credentials - Present as None: chained data from upstream block - Absent: forked/needs re-authentication Also adds pre-run validation for the missing key case and makes error messages provider-agnostic. Co-Authored-By: Claude Opus 4.6 --- autogpt_platform/backend/backend/data/graph.py | 2 +- autogpt_platform/backend/backend/data/graph_test.py | 9 +++++---- autogpt_platform/backend/backend/executor/utils.py | 13 +++++++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/autogpt_platform/backend/backend/data/graph.py b/autogpt_platform/backend/backend/data/graph.py index 759a303c4b..3340716da8 100644 --- a/autogpt_platform/backend/backend/data/graph.py +++ b/autogpt_platform/backend/backend/data/graph.py @@ -683,7 +683,7 @@ class GraphModel(Graph, GraphMeta): continue for key, value in node.input_default.items(): if isinstance(value, dict) and "_credentials_id" in value: - value["_credentials_id"] = None + del value["_credentials_id"] def validate_graph( self, diff --git a/autogpt_platform/backend/backend/data/graph_test.py b/autogpt_platform/backend/backend/data/graph_test.py index 066cd3a3de..ff49db531e 100644 --- a/autogpt_platform/backend/backend/data/graph_test.py +++ b/autogpt_platform/backend/backend/data/graph_test.py @@ -560,8 +560,9 @@ def test_reassign_ids_clears_credentials_id(): GraphModel._reassign_ids(graph, user_id="new-user", graph_id_map={}) - # _credentials_id should be cleared - assert graph.nodes[0].input_default["spreadsheet"]["_credentials_id"] is None + # _credentials_id key should be removed (not set to None) so that + # _acquire_auto_credentials correctly errors instead of treating it as chained data + assert "_credentials_id" not in graph.nodes[0].input_default["spreadsheet"] def test_reassign_ids_preserves_non_credential_fields(): @@ -668,8 +669,8 @@ def test_reassign_ids_handles_multiple_credential_fields(): GraphModel._reassign_ids(graph, user_id="new-user", graph_id_map={}) - assert graph.nodes[0].input_default["spreadsheet"]["_credentials_id"] is None - assert graph.nodes[0].input_default["doc_file"]["_credentials_id"] is None + assert "_credentials_id" not in graph.nodes[0].input_default["spreadsheet"] + assert "_credentials_id" not in graph.nodes[0].input_default["doc_file"] assert graph.nodes[0].input_default["plain_input"] == "not a dict" diff --git a/autogpt_platform/backend/backend/executor/utils.py b/autogpt_platform/backend/backend/executor/utils.py index e3d24be556..ffccd125b9 100644 --- a/autogpt_platform/backend/backend/executor/utils.py +++ b/autogpt_platform/backend/backend/executor/utils.py @@ -353,6 +353,15 @@ async def _validate_node_input_credentials( ) if field_value and isinstance(field_value, dict): + if "_credentials_id" not in field_value: + # Key removed (e.g., on fork) — needs re-auth + has_missing_credentials = True + credential_errors[node.id][field_name] = ( + "Authentication missing for the selected file. " + "Please re-select the file to authenticate with " + "your own account." + ) + continue cred_id = field_value.get("_credentials_id") if cred_id and isinstance(cred_id, str): try: @@ -367,9 +376,9 @@ async def _validate_node_input_credentials( if not creds: has_missing_credentials = True credential_errors[node.id][field_name] = ( - "The saved Google credentials are not available " + "The saved credentials are not available " "for your account. Please re-select the file to " - "authenticate with your own Google account." + "authenticate with your own account." ) # If node has optional credentials and any are missing, mark for skipping