odoo/odoo · error · ValidationError
To explicitly indicate no (valid) VAT, use '/' instead.
Error message
To explicitly indicate no (valid) VAT, use '/' instead.
What it means
Raised by base_vat's _run_vat_checks() when the partner's vat value is exactly one character long and is neither '/' nor handled by a softer validation mode. Odoo uses '/' as the explicit sentinel meaning 'this partner has no VAT number', so any other single-character VAT is treated as invalid input rather than being checked.
Source
Thrown at addons/base_vat/models/res_partner.py:117
)
# Field representing whether vies_valid is relevant for selecting a fiscal position on this partner
perform_vies_validation = fields.Boolean(compute='_compute_perform_vies_validation')
# We put on inverse because a compute with a dependency to itself is not well managed in the ORM (it should be triggered first)
country_id = fields.Many2one(inverse="_inverse_vat", store=True)
vat = fields.Char(inverse="_inverse_vat", store=True)
@api.model
def _run_vat_checks(self, country, vat, partner_name='', validation='error'):
""" OVERRIDE """
if not country or not vat:
return vat, False
if len(vat) == 1:
if vat == '/' or not validation:
return vat, False
if validation == 'setnull':
return '', False
if validation == 'error':
raise ValidationError(_("To explicitly indicate no (valid) VAT, use '/' instead. "))
vat_prefix, vat_number = self._split_vat(vat)
if vat_prefix == 'EU' and country not in self.env.ref('base.europe').country_ids:
# Foreign companies that trade with non-enterprises in the EU
# may have a VATIN starting with "EU" instead of a country code.
return vat, False
do_eu_check = False
prefixed_country = ''
eu_prefix_country_group = self.env['res.country.group'].search([('code', '=', 'EU_PREFIX')], limit=1)
country_code = EU_EXTRA_VAT_CODES_INV.get(vat_prefix, vat_prefix)
if country_code in eu_prefix_country_group.country_ids.mapped('code'):
if 'EU_PREFIX' in country.country_group_codes and vat_prefix:
vat = vat_number
prefixed_country = vat_prefix
else:
do_eu_check = True
View on GitHub (pinned to 1e661df964)
Solutions
- Use '/' as the vat value to explicitly record that the partner has no (valid) VAT number.
- Leave the vat field empty (falsy) instead of writing a placeholder character — empty values skip validation entirely.
- For bulk imports where the source data is dirty, pre-clean single-character VATs to '' or '/' before writing to res.partner.
Example fix
# before
partner.write({'vat': '-'}) # ValidationError
# after
partner.write({'vat': '/'}) # explicit 'no VAT' sentinel Defensive patterns
Strategy: validation
Validate before calling
def normalize_vat(vat):
if vat and len(vat) == 1 and vat != '/':
return '' # or '/' to explicitly mark 'no VAT'
return vat
partner.write({'vat': normalize_vat(raw_vat)}) Try / catch
from odoo.exceptions import ValidationError
try:
partner.write({'vat': raw})
except ValidationError:
partner.write({'vat': '/'}) # explicit no-VAT sentinel Prevention
- Use '/' or empty string for partners without a VAT number; never placeholder characters.
- Pre-clean VAT columns in import scripts: strip whitespace, map single-char junk to '' or '/'.
- Add unit tests asserting single-character VATs are normalized before reaching base_vat.
When it happens
Trigger: Setting res_partner.vat to a single non-'/' character (e.g. '0', 'x', '-') while the partner has a country with VAT validation active and validation='error' (the default on create/write of vat).
Common situations: Data imports or CSV syncs that map an empty/placeholder VAT column to a stray character; users typing '-' or '.' to mean 'none'; connectors pushing partial values.
Related errors
- The %(vat_label)s number [%(wrong_vat)s] for %(record_label)
- The %(vat_label)s number [%(wrong_vat)s] for %(record_label)
- The country of the foreign VAT number could not be detected.
- You cannot create a fiscal position with a foreign VAT withi
- You cannot create a fiscal position with a country outside o
AI-assisted analysis of odoo/odoo@1e661df964 (2026-08-15).
Data as JSON: /api/errors/4cfa966ee81d8b7c.
Report an issue: GitHub.