odoo/odoo · error · UserError

You cannot add/modify entries prior to and inclusive of: %(l

Error message

You cannot add/modify entries prior to and inclusive of: %(lock_date_info)s.

What it means

UserError from _check_fiscal_lock_dates when a move's date falls on or before an active lock date of its company (fiscal year lock, plus hard sale/purchase locks depending on journal type, fiscalyear=True, hard=True). Lock dates freeze the ledger so reported periods cannot change; the message enumerates which locks are violated via _format_lock_dates.

Source

Thrown at addons/account/models/account_move.py:2824

        ''', tuple(moves.ids)))

    def _check_fiscal_lock_dates(self):
        if self.env.context.get('bypass_lock_check') is BYPASS_LOCK_CHECK:
            return
        for move in self:
            journal = move.journal_id
            violated_lock_dates = move.company_id._get_lock_date_violations(
                move.date,
                fiscalyear=True,
                sale=journal and journal.type == 'sale',
                purchase=journal and journal.type == 'purchase',
                tax=False,
                hard=True,
            )
            if violated_lock_dates:
                message = _("You cannot add/modify entries prior to and inclusive of: %(lock_date_info)s.",
                            lock_date_info=self.env['res.company']._format_lock_dates(violated_lock_dates))
                raise UserError(message)
        return True

    @api.constrains('auto_post', 'invoice_date')
    def _require_bill_date_for_autopost(self):
        """Vendor bills must have an invoice date set to be posted. Require it for auto-posted bills."""
        for record in self:
            if record.auto_post != 'no' and record.is_purchase_document() and not record.invoice_date:
                raise ValidationError(_("For this entry to be automatically posted, it required a bill date."))

    @api.constrains('journal_id', 'move_type')
    def _check_journal_move_type(self):
        for move in self:
            if move.is_purchase_document(include_receipts=True) and move.journal_id.type != 'purchase':
                raise ValidationError(_("Cannot create a purchase document in a non purchase journal"))
            if move.is_sale_document(include_receipts=True) and move.journal_id.type != 'sale':
                raise ValidationError(_("Cannot create a sale document in a non sale journal"))

    @api.constrains('line_ids', 'fiscal_position_id', 'company_id')

View on GitHub (pinned to 1e661df964)

Solutions

  1. Set the move's date to a date after all violated lock dates
  2. Ask an advisor/admin to adjust or clear the lock dates: Settings > Accounting > Lock Dates (or write on res.company lock fields) and retry
  3. If the entry genuinely belongs in the locked period, temporarily lift the hard lock, make the change, restore it — with auditor awareness
  4. Use context keys only if the code path legitimately bypasses checks (e.g. closing operations), never to silently edit locked periods

Example fix

// before
move.write({'date': '2023-12-15'})  # company fiscal year locked at 2023-12-31

// after
lock = move.company_id.fiscalyear_lock_date
safe_date = lock + timedelta(days=1) if lock and fields.Date.to_date('2023-12-15') <= lock else '2023-12-15'
move.write({'date': safe_date})
Defensive patterns

Strategy: validation

Validate before calling

def lock_violations(move, date):
    return move.company_id._get_lock_date_violations(date, fiscalyear=True, sale=move.journal_id.type=='sale', purchase=move.journal_id.type=='purchase', tax=False, hard=True)

Try / catch

try:
    move.write({'date': new_date})
except UserError as e:
    if 'lock' in str(e).lower():
        move.write({'date': safe_after_lock(move.company_id)})

Prevention

When it happens

Trigger: Creating/editing/posting a move whose date <= company hard lock date: write({'date': ...}) backdating an entry; posting an old invoice; creating entries dated in a closed fiscal year; the write() path also calls this when changing name/date of posted moves or unposting.

Common situations: Backdating invoices after year-end closing; users in a period already locked by the accountant; imports with historical dates after locks were set; trying to reset a posted move to draft across the lock.

Related errors


AI-assisted analysis of odoo/odoo@1e661df964 (2026-08-15). Data as JSON: /api/errors/d7da1185eecabe83. Report an issue: GitHub.