Inleiding
Als je al even met Odoo werkt, is de kans groot dat je deze foutmelding al eens bent tegengekomen:
ValueError: Expected singleton
Deze fout hoort bij de meest voorkomende problemen met de ORM in Odoo. Ze verschijnt wanneer een functie één record verwacht, maar meerdere krijgt. Hoewel de melding technisch klinkt, ligt de oorzaak vaak in een simpel misverstand over hoe Odoo met recordsets omgaat.
In deze gids leggen we in heldere stappen uit wat de “Expected Singleton”-fout inhoudt, waarom ze voorkomt en hoe je ze veilig oplost zonder je bedrijfslogica of integraties te schaden.
Wat betekent “Expected Singleton” in Odoo?
Odoo’s ORM (Object Relational Mapping) werkt niet met losse objecten, maar met recordsets. Een recordset kan namelijk bestaan uit:
- Één record
- Meerdere records
- Geen records
Wanneer Odoo een methode uitvoert die ontworpen is voor één enkel record, maar de recordset meerdere items bevat, geeft het systeem de volgende foutmelding:
ValueError: Expected singleton
Kort door de bocht:
Odoo verwachtte één record. Het kreeg er meerdere.
Je ziet deze fout vooral in situaties zoals:
- Serverlogs
- Maatwerkmodules
- Berekeningsvelden (computed fields)
- Actieknoppen
- Automatische acties
- Bulkbewerkingen
Het begrijpen van het gedrag van recordsets is cruciaal om dit probleem correct aan te pakken.
Waarom treedt deze fout op?
1. Verkeerd begrip van recordsets
In Odoo is self in de meeste gevallen gewoon een recordset.
Zelfs als je denkt dat je op één record werkt, kan Odoo jouw methode aanroepen met meerdere records tijdens bijvoorbeeld:
- Massabewerkingen vanuit een boomweergave
- Geautomatiseerde workflows
- Serveracties
- API-imports
Als je code ervan uitgaat dat er maar één record is, faalt ze zodra dat niet het geval is.
2. Ontbrekende iteratie in een methode
Veelvoorkomend probleem in codevoorbeelden:
def action_confirm(self): self.state = 'confirmed'
Als self meerdere records bevat ontstaat er onduidelijkheid en kan de fout optreden.
Correcte aanpak:
def action_confirm(self): for record in self: record.state = 'confirmed'
3. Onjuist gebruik van ensure_one()
Odoo biedt een hulpmiddel:
self.ensure_one()
Dit dwingt af dat er precies één record wordt behandeld; bij meerdere records gooit het bewust de singleton-fout.
Gebruik ensure_one() alleen wanneer je bedrijfsregels écht een enkel record vereisen (bijvoorbeeld het openen van een formulier voor één entiteit).
4. Search die meerdere records teruggeeft
Voorbeeldsituatie:
partner = self.env['res.partner'].search([('name', '=', 'John')])
Als er meerdere partners met naam “John” bestaan en de rest van de code één record verwacht, levert dat de fout op.
Veiliger alternatief:
partner = self.env['res.partner'].search([('name', '=', 'John')], limit=1)
5. Verwarring rond relationele velden
Fouten ontstaan vaak door Many2one- of One2many-relaties.
Voorbeeldsituatie:
self.order_line.product_id.name
Als order_line meerdere regels bevat, is zo’n expressie dubbelzinnig en kan ze de singleton-fout veroorzaken.
Hoe los je de Expected Singleton-fout op?
Stap 1 – Itereer over recordsets
Gouden regel in Odoo:
Ga er steeds vanuit dat self meerdere records kan bevatten.
for record in self: record.process_logic()
Stap 2 – Gebruik limit=1 waar nodig
Wanneer slechts één record logisch is:
record = self.env['model.name'].search(domain, limit=1)
Stap 3 – Controleer relationele velden
Let op:
- Many2one-relaties
- One2many-collecties
- Domain-filters
Zorg dat je niet onbedoeld met meerdere rijen werkt.
Stap 4 – Kijk naar API- of importprocessen
In omgevingen met veel integraties veroorzaken bulkacties deze fout vaak omdat meerdere records tegelijk worden verwerkt.
Als jouw Odoo-data vanuit externe systemen gesynchroniseerd wordt, ontwerp dan logica die veilig in batches draait.
Hoe voorkom je deze fout bij toekomstige Odoo-ontwikkeling?
- Vermijd aannames over single-record context
- Test functies ook met meerdere geselecteerde records
- Gebruik standaard iteraties
- Voeg limit=1 bewust toe wanneer van toepassing
- Houd relationele velden overzichtelijk
In complexe integraties duiken dit soort fouten vaak op tijdens automatische imports of geplande jobs. Batch-veilige ontwerpen voorkomen instabiliteit.
Hoe gaat Dasolo om met recordset- en ORM-fouten?
De “Expected Singleton”-fout wijst zelden alleen op een slordigheid in de code. In goed gestructureerde Odoo-omgevingen onthult ze vaak diepere veronderstellingen over recordsetgedrag, verkeerd gebruik van de ORM of inconsistenties in de datastroom.
Bij Dasolo pakken we ORM-fouten aan door te kijken naar hoe recordsets doorheen een module worden gebruikt. Singleton-problemen ontstaan meestal wanneer bedrijfslogica is geschreven voor één record, maar in realiteit op meerdere records wordt uitgevoerd — vooral in geautomatiseerde workflows, integraties of computed fields.
Om terugkerende singleton-excepties te vermijden, focussen we op:
- Consistente iteratiepatronen over recordsets
- Verstandig gebruik van ensure_one()
- Voorspelbare domain-filters
- Schone relationele modellering
- Beheersbare triggers voor automatisering
Als je ORM-logica vanaf het begin schaalbaar ontwerpt, dalen de onverwachte runtime-fouten in productie aanzienlijk.
Samenvatting
De Odoo “Expected Singleton”-fout is een veelvoorkomende ORM-exceptie: code probeert meerdere records te verwerken terwijl er maar één verwacht wordt. Hoewel het op het eerste gezicht een simpele ontwikkelaarsfout lijkt, wijst ze vaak op bredere problemen in de manier waarop recordsets of geautomatiseerde processen zijn opgebouwd.
Door te begrijpen hoe Odoo met recordsets omgaat en veilige iteratiepatronen toe te passen, kun je deze fout terugdringen. Duidelijke recordafhandeling, expliciete controles en gecontroleerde automatisering zijn cruciaal voor een stabiele Odoo-omgeving.
Correct aangepakte singleton-fouten zijn eigenlijk nuttige waarschuwingssignalen: ze helpen je de codekwaliteit te verbeteren en de betrouwbaarheid van het systeem op langere termijn te verhogen.
Veelgestelde vragen
Nee. Ze komt voor in Odoo 14, 15, 16 en 17.
Nee. Het gaat om een logische fout in de manier waarop records worden verwerkt.
Nee. Alleen wanneer de bedrijfslogica strikt vereist dat er precies één record verwerkt wordt.