From ed6f8216d83c9188564781355a48154219127ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20L=C3=B6ffler?= Date: Fri, 11 Sep 2026 09:18:31 +0200 Subject: [PATCH] fix(terraform): omit empty team_id from /key/update payload UpdateKey always sent team_id, so a key with no team sent team_id: "" and the proxy rejected it with a 500 ("Team object not found for team change validation"). Any update or import of a teamless key failed outright. Only send team_id when it is set, matching how budget_duration is already handled. --- terraform/provider/litellm/client.go | 7 ++++- .../provider/litellm/resource_key_test.go | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/terraform/provider/litellm/client.go b/terraform/provider/litellm/client.go index e68b8a3a80b..26e6a91a15c 100644 --- a/terraform/provider/litellm/client.go +++ b/terraform/provider/litellm/client.go @@ -125,7 +125,6 @@ func (c *Client) UpdateKey(key *Key) (*Key, error) { // Create a new map with only the fields that can be updated updateData := map[string]interface{}{ "key": key.Key, - "team_id": key.TeamID, "key_alias": key.KeyAlias, "aliases": key.Aliases, "permissions": key.Permissions, @@ -144,6 +143,12 @@ func (c *Client) UpdateKey(key *Key) (*Key, error) { updateData["model_tpm_limit"] = key.ModelTPMLimit } + // The proxy rejects an empty team_id with a 500 ("Team object not found"), + // so only send it when set. + if key.TeamID != "" { + updateData["team_id"] = key.TeamID + } + // The proxy rejects an empty-string budget_duration with a 400, so only // send it when set. if key.BudgetDuration != "" { diff --git a/terraform/provider/litellm/resource_key_test.go b/terraform/provider/litellm/resource_key_test.go index 66291eadcc5..8252085a847 100644 --- a/terraform/provider/litellm/resource_key_test.go +++ b/terraform/provider/litellm/resource_key_test.go @@ -319,6 +319,34 @@ func TestUpdateKeyOmitsEmptyBudgetDuration(t *testing.T) { } } +// The proxy 500s on team_id: "" with "Team object not found", so a teamless key +// must omit it from the update payload entirely. +func TestUpdateKeyOmitsEmptyTeamID(t *testing.T) { + var captured map[string]interface{} + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + body, _ := io.ReadAll(r.Body) + json.Unmarshal(body, &captured) + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(`{"key": "sk-test"}`)) + })) + defer srv.Close() + + client := NewClient(srv.URL, "test-key", true) + if _, err := client.UpdateKey(&Key{Key: "sk-test"}); err != nil { + t.Fatalf("UpdateKey returned error: %v", err) + } + if _, present := captured["team_id"]; present { + t.Errorf("update payload contains empty team_id: %v", captured["team_id"]) + } + + if _, err := client.UpdateKey(&Key{Key: "sk-test", TeamID: "team-1"}); err != nil { + t.Fatalf("UpdateKey returned error: %v", err) + } + if captured["team_id"] != "team-1" { + t.Errorf("team_id = %v, want team-1", captured["team_id"]) + } +} + func TestResourceKeyUpdateFailureKeepsPriorState(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json")