Saltar al contenido principal
GoCardless API · invalid_state · 409

GoCardless 409 idempotent_creation_conflict: el cobro ya existía

Este error asusta más de lo que debería. GoCardless responde 409 idempotent_creation_conflict cuando recibe por segunda vez una petición de creación con una clave de idempotencia que ya usó. Bien llevado, es justo lo que impide cobrar dos veces el mismo recibo.

FlexigoTech · Responsable: Víctor Gómez · Actualizado el 6 de noviembre de 2026

Lo esencial

Módulo
GoCardless
Versiones
Odoo 17, 18, 19 y 20
Comprobado
en el código del conector, versión 17.0, 18.0, 19.0 y 20.0 · en las fuentes enlazadas al final
Lectura
3 min

Qué dice GoCardless

ReasonTipoHTTPTexto de GoCardless
idempotent_creation_conflictinvalid_state409A resource already exists for the supplied idempotency key.

La página de límites de GoCardless lo completa: si ya existe un recurso con esa clave, la respuesta es un 409 con links.conflicting_resource_id, que señala el recurso que ya está creado. Las claves pueden tener hasta 128 caracteres y GoCardless las recuerda al menos 30 días.

Tarjeta del error idempotent_creation_conflict de GoCardless
El reason, el código HTTP 409 y el texto con el que lo documenta GoCardless.

El problema que resuelve

Una petición puede tardar: GoCardless corta las que pasan de 29 segundos, y la red puede cortarse antes. Si Odoo pide un cobro y no recibe respuesta, no sabe si GoCardless lo creó. Repetir la petición sin más es peligroso; la propia documentación de GoCardless avisa de que reintentar sin clave de idempotencia tras un tiempo de espera agotado puede cobrar el mismo pago dos veces.

Con clave, el segundo intento no crea nada: si el primero llegó, GoCardless contesta con este 409 y el identificador del cobro que ya existe.

Cómo lo usa el conector

El conector manda una clave de idempotencia en cada petición que crea un cobro, un reembolso, un reintento o la solicitud del mandato. La clave no es aleatoria. Se calcula con la operación, la transacción de Odoo y el identificador de la base de datos, de modo que:

  • repetir el mismo cobro manda exactamente la misma clave;
  • una copia de la base para pruebas no choca con la de producción aunque las dos emitan la misma factura.

Cuando llega el 409, el conector lee conflicting_resource_id, pide ese recurso a GoCardless y lo adopta como respuesta. Para ti no hay error: la transacción queda enlazada al cobro que ya existía, y la factura sigue su curso normal.

Cuando GoCardless no contesta

Si la petición se queda sin respuesta, el conector la repite una vez con la misma clave. Sin clave no repite nada. Si tampoco hay respuesta, avisa sin dar el cobro por perdido: «GoCardless no respondió, así que aún no se sabe si aceptó la solicitud. Se volverá a enviar, de forma segura, en menos de una hora.». La transacción queda pendiente, no en error, porque en error Odoo podría generar otro cobro con otra referencia y otra clave.

Ese aviso sale en el idioma de quien lanza el cobro. Si lo lanza una tarea programada, como la renovación de una suscripción o el reenvío del propio conector, se escribe sin nadie delante: en una base de datos creada en castellano sale así, y en una creada en inglés y pasada después a castellano, en inglés: «GoCardless did not answer, so it is not known yet whether it took the request. It will be sent again, safely, within the hour.».

Esquema: qué responde GoCardless con un 409 y qué hace Odoo con el conector
Esquema hecho a partir del código del conector (17.0, 18.0, 19.0 y 20.0) y de la documentación de GoCardless; lo tachado es lo que el 409 evita.

Qué hacer

Con el conector, normalmente nada: el 409 se resuelve solo. Si lo ves en otro programa conectado a la misma cuenta de GoCardless, comprueba dos cosas. La primera, que no estés reutilizando una clave para operaciones distintas. La segunda, que el recurso de conflicting_resource_id sea el que esperabas: si lo es, el reintento ha funcionado como debe. Si no lo es, guarda el request_id de la respuesta: GoCardless pide incluirlo al contactar con su soporte, y el conector lo añade a sus mensajes de error.

¿Un 409 significa que el cliente pagó dos veces?

Al revés. Significa que GoCardless se negó a crear el segundo cobro porque la clave ya tenía uno. El cliente paga una sola vez.

¿Qué pasa si se cambia la referencia de la transacción?

Cambia la clave, y GoCardless lo trata como un cobro nuevo. Por eso el conector deja pendiente, y no en error, un cobro sin respuesta: así no se crea otro con otra referencia.

Con nuestro conector

En Odoo 17, 18, 19 y 20 el conector aplica la regla que GoCardless pide para no cobrar dos veces: clave fija por operación, repetición solo con la misma clave y adopción del recurso existente cuando llega el 409.

Sigue leyendo

Error mandate_is_inactive de GoCardless al crear un cobro desde OdooGoCardless responde mandate_is_inactive al crear un pago con un mandato cancelado, fallido o caducado. Por qué pasa y cómo lo resuelve el conector en Odoo.Error retry_failed de GoCardless al reintentar un cobro desde OdooGoCardless responde retry_failed si el pago no ha fallado o ya no admite reintentos. Cuándo sale en Odoo el botón «Reintentar el cobro» y qué hace el conector.Webhook de GoCardless: 498 Token Invalid, 204 y la firma Webhook-SignatureGoCardless pide 498 si la firma Webhook-Signature no cuadra y 204 si no reconoce el evento. Qué contesta Odoo 17, 18, 19 y 20 y por qué en 20 es un 401.
Comprobado en el código del conector (versión 17.0, 18.0, 19.0 y 20.0) y en las fuentes enlazadas

Fuentes

  • docs.gocardless.com/docs/api-reference/limits
  • Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 462 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 352 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 68 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 391 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 357 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: models/payment_provider.py, línea 373 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 299 en 17.0 (d203ee6), línea 299 en 18.0 (e2ab18b), línea 299 en 19.0 (ce7f5a3) y línea 310 en 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 478 en 17.0 (d203ee6), línea 478 en 18.0 (e2ab18b), línea 478 en 19.0 (ce7f5a3) y línea 483 en 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: i18n/es.po, línea 30 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: __manifest__.py, línea 31 en 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) y 20.0 (688d86b)
  • docs.gocardless.com/docs/api-reference/responses-and-errors
  • Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 123 en 17.0 (d203ee6), línea 123 en 18.0 (e2ab18b), línea 123 en 19.0 (ce7f5a3) y línea 126 en 20.0 (688d86b)
  • Código del módulo: flexigo_payment_gocardless: models/payment_transaction.py, línea 247 en 17.0 (d203ee6), línea 247 en 18.0 (e2ab18b), línea 247 en 19.0 (ce7f5a3) y línea 258 en 20.0 (688d86b)
  • github.com/odoo/odoo/blob/17.0/odoo/http.py