From cff3a5e9b6200fe1a5a99c7413b1e7391249fcb3 Mon Sep 17 00:00:00 2001 From: Matthew Howard <78384492+matthowardcohere@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:39:42 -0400 Subject: [PATCH] fix(credential): recognize the credential_name unique-constraint conflict Adds isCredentialConflictError and wires it into handleCredentialAPIResponse so resourceLiteLLMCredentialCreate can tell a name conflict apart from other failures. Fixes https://github.com/BerriAI/terraform-provider-litellm/issues/8 --- terraform/provider/litellm/utils.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/terraform/provider/litellm/utils.go b/terraform/provider/litellm/utils.go index 5e81766d3f3..2a35973c929 100644 --- a/terraform/provider/litellm/utils.go +++ b/terraform/provider/litellm/utils.go @@ -202,6 +202,28 @@ func isCredentialNotFoundError(errResp ErrorResponse) bool { return false } +// isCredentialConflictError checks if the error response indicates a credential +// name collision. LiteLLM surfaces this as a 500 carrying the underlying Prisma +// unique-constraint message on credential_name. See +// https://github.com/BerriAI/terraform-provider-litellm/issues/8. +func isCredentialConflictError(errResp ErrorResponse) bool { + if msg, ok := errResp.Error.Message.(string); ok { + if strings.Contains(msg, "Unique constraint failed") && strings.Contains(msg, "credential_name") { + return true + } + } + + if msgMap, ok := errResp.Error.Message.(map[string]interface{}); ok { + if errStr, ok := msgMap["error"].(string); ok { + if strings.Contains(errStr, "Unique constraint failed") && strings.Contains(errStr, "credential_name") { + return true + } + } + } + + return false +} + // handleCredentialAPIResponse handles API responses specifically for credential operations func handleCredentialAPIResponse(resp *http.Response, result interface{}, client *Client) error { bodyBytes, err := io.ReadAll(resp.Body) @@ -219,6 +241,9 @@ func handleCredentialAPIResponse(resp *http.Response, result interface{}, client if isCredentialNotFoundError(errResp) { return fmt.Errorf("credential_not_found") } + if isCredentialConflictError(errResp) { + return fmt.Errorf("credential_conflict") + } } return fmt.Errorf("API request failed: Status: %s, Response: %s", resp.Status, client.redactSensitiveData(string(bodyBytes)))