Skip to content

kw_api: ApiKey.create is broken on Odoo 17+ — no new API key can be created #1

Description

@brmk

What breaks

No new API key can be created on Odoo 17 or later. Every attempt fails with

TypeError: list indices must be integers or slices, not str

Why

kw_api/models/api_key.py:43-46 is written for the pre-17 ORM signature:

@api.model
def create(self, vals):
    vals['api_key'] = secrets.token_urlsafe(120)
    return super(ApiKey, self).create(vals)

Since Odoo 17, BaseModel.create is @api.model_create_multi and receives a list of
dicts. vals is that list, so the subscript raises.

Reproduce

Odoo 19.0, clean database, kw_api installed:

env['kw.api.key'].create({'name': 'test', 'code': 'test'})

The UI form fails the same way — the model is unreachable through any path that creates a
record.

Why this stays hidden

An API key is a plain row. Every key created before the upgrade to 17.0+ keeps
authenticating perfectly, so the module looks healthy indefinitely. The failure only
surfaces the first time somebody needs a new key, and those moments are exactly the
ones where you least want a blocker:

  • Key rotation — a key leaks, or policy requires periodic rotation. You cannot issue
    the replacement, so the only way to cut off the old key is to delete it and take the
    integration down.
  • Onboarding a new consumer — a second storefront, a mobile app, a partner system.
    Every new integration needs its own key, and none can be issued.
  • Standing up a staging or local environment — a fresh database needs a key before the
    API can be exercised at all. This is how we hit it: seeding a local Odoo 19 for testing
    died on the first create.
  • Revoking one consumer's access — with per-consumer keys you revoke one and reissue
    the rest. Not possible.

In other words the module keeps working right up until the moment you need it to be
manageable, and then offers no path forward except SQL.

Affected

Present on both the 18.0 and 19.0 branches (kw_api 19.0.1.4.2), byte-identical.

Suggested fix

@api.model_create_multi
def create(self, vals_list):
    for vals in vals_list:
        vals['api_key'] = secrets.token_urlsafe(120)
    return super().create(vals_list)

A pull request is attached.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions