Skip to content

Conversation

@loumalouomega
Copy link

@loumalouomega loumalouomega commented Jan 9, 2026

Description

This PR fixes a compilation error encountered when using Visual Studio 2022 version 17.12 (MSVC 14.44) in C++20 mode.

The MSVC STL (specifically the <span header) has introduced internal checks that reference the macro _BACKUP_ITERATOR_DEBUG_LEVEL. In certain build environments—particularly those involving complex Python bindings like Kratos Multiphysics—this macro is expected by the STL but remains undeclared, leading to the following error:

error C2065: '_BACKUP_ITERATOR_DEBUG_LEVEL' : undeclared identifier
error C3861: '_BACKUP_ITERATOR_DEBUG_LEVEL': identifier not found

Proposed Changes

Inserted a preprocessor guard in include/pybind11/pybind11.h to ensure _BACKUP_ITERATOR_DEBUG_LEVEL is defined to 0 if it is not already set. This allows the MSVC STL headers to resolve their internal iterator debugging logic correctly. I understand that maybe the placement can be improved in order to not add "garbage" to the main include file, I am open to suggestions.

// See Issue #5956. This fixes compilation failure with MSVC 17.12 (v14.44) and C++20: 
// '_BACKUP_ITERATOR_DEBUG_LEVEL' undeclared when including span header from STL.
#if defined(_MSC_VER)
    #ifndef _BACKUP_ITERATOR_DEBUG_LEVEL
        #define _BACKUP_ITERATOR_DEBUG_LEVEL 0
    #endif
#endif

Motivation and Context

How Has This Been Tested?

  • Confirmed that the error is resolved in the Kratos Multiphysics build pipeline using the specified MSVC version.

Suggested changelog entry:

loumalouomega and others added 2 commits January 9, 2026 11:07
…BACKUP_ITERATOR_DEBUG_LEVEL' undeclared when including span header from STL.
@rwgk
Copy link
Collaborator

rwgk commented Jan 10, 2026

Original Prompt (Cursor Claude Opus 4.5)

Could you please read /home/rgrossekunst/wrk/logs/gh_pr_info_pybind_pybind11_5957_2026-01-10+105144.md, which goes with this branch?

I'm not sure this is a good fix/workaround. Defining an underscore symbol just because it's undefined seems like a setup for accidents.

A second concern is that we're not adding a test to the pybind11 CI.

Maybe let's start from here: What do we need in .github/workflows/ci.yml to reproduce the failure? After we have that: what could be a better fix? Do we even need one? What I have in mind: could this issue be worked around by client code simply including certain headers, maybe in the right order?


Analysis

PR Summary

PR #5957 proposes adding this to include/pybind11/pybind11.h:

// See Issue #5956. This fixes compilation failure with MSVC 17.12 (v14.44) and C++20:
// '_BACKUP_ITERATOR_DEBUG_LEVEL' undeclared when including span header from STL.
#if defined(_MSC_VER)
#    ifndef _BACKUP_ITERATOR_DEBUG_LEVEL
#        define _BACKUP_ITERATOR_DEBUG_LEVEL 0
#    endif
#endif

The issue (#5956) reports a compilation failure when building Kratos Multiphysics with MSVC 17.12 and C++20, where the <span> header complains about _BACKUP_ITERATOR_DEBUG_LEVEL being undeclared.


Key Finding: The pybind11 CI Already Tests This Scenario

Looking at the CI configuration in .github/workflows/ci.yml:

- runs-on: windows-latest
  python-version: '3.14'
  cmake-args: -DCMAKE_CXX_STANDARD=20

The GitHub Actions windows-latest runner uses VS 17.14 (even newer than the 17.12 in the bug report). The CI already passes with C++20 on Windows without this workaround.

Additional Windows C++20+ tests that already exist:

  • windows-latest + Python 3.14 + C++20
  • windows-latest + Python 3.14t + C++23
  • windows-latest + pypy3.11 + C++20
  • windows-2022 + Python 3.9 + C++20

Why This Issue Doesn't Reproduce in pybind11 CI

  1. pybind11 doesn't include <span> - There's no #include <span> anywhere in the pybind11 codebase

  2. The CI tests pass - With newer MSVC (17.14) and C++20/C++23, the tests pass without this workaround

  3. The issue is Kratos-specific - The bug report explicitly says this only happens in "Kratos Multiphysics" builds:

    "In certain build environments—particularly those involving complex Python bindings like Kratos Multiphysics—this macro is expected by the STL but remains undeclared"


The Real Problem

The _BACKUP_ITERATOR_DEBUG_LEVEL macro is an internal MSVC STL macro used for iterator debugging. The STL uses macros like _ITERATOR_DEBUG_LEVEL to control iterator debugging, and _BACKUP_ITERATOR_DEBUG_LEVEL appears to be used internally when temporarily modifying the debug level.

The fact that this macro is "undeclared" suggests Kratos is likely doing something that interferes with the STL's internal iterator debugging mechanism—possibly:

  • Defining _ITERATOR_DEBUG_LEVEL after some STL headers are already included
  • Including STL headers in an unusual order
  • Using /D_ITERATOR_DEBUG_LEVEL=... compiler flags inconsistently across translation units
  • Some other macro manipulation that confuses the STL's internal state

Why the Proposed Fix is Problematic

Blindly defining _BACKUP_ITERATOR_DEBUG_LEVEL 0 is dangerous:

  1. Masks the real bug - The real issue is in client code (Kratos), not pybind11

  2. Touches internal STL macros - These are implementation details that could change between MSVC versions; defining them externally is undefined behavior territory

  3. Could disable iterator debugging - Setting it to 0 might suppress legitimate safety checks that help catch bugs

  4. Sets a dangerous precedent - pybind11 shouldn't work around bugs in downstream projects by defining internal compiler/STL macros

  5. No test coverage - As noted in the original prompt, there's no way to add a CI test because the issue doesn't reproduce in pybind11's test suite


Recommendation

This fix should NOT be merged into pybind11.

Reasons:

  1. The issue cannot be reproduced in pybind11's CI (which already tests Windows + C++20/23 with newer MSVC)
  2. The issue is specific to Kratos, not a general pybind11 problem
  3. Defining internal STL macros is inappropriate for a library like pybind11

The Fix Belongs in Kratos

Kratos should either:

  1. Include STL foundation headers first - Before any STL headers or pybind11:

    #if defined(_MSC_VER)
    #    include <yvals_core.h>  // Ensures all iterator debug macros are defined
    #endif
  2. Ensure consistent _ITERATOR_DEBUG_LEVEL settings - Across all translation units and before any STL headers are included

  3. Fix the include order issue - Whatever is causing STL headers to be included before the iterator debug macros are properly set up

Alternative Client-Side Workaround

If Kratos users need an immediate workaround, they can add this to their own code before including pybind11:

// Workaround for MSVC 17.12 iterator debug macro issue
// Add this BEFORE including any pybind11 or STL headers
#if defined(_MSC_VER)
#    include <yvals_core.h>
#endif

#include <pybind11/pybind11.h>

No CI Changes Needed

Since:

  • The pybind11 CI already tests Windows + MSVC + C++20/C++23
  • The CI uses MSVC 17.14 (newer than the reported 17.12)
  • The tests pass without any workaround

There's no CI change that would help reproduce this issue, because the issue is not in pybind11.


Summary

Question Answer
Is this a pybind11 bug? No - CI passes with newer MSVC and C++20
Can we reproduce in CI? No - Issue is Kratos-specific
Should we merge this PR? No - It's a workaround for client code issues
Where should the fix go? In Kratos - They should fix their include order
Is the proposed fix safe? No - Defining internal STL macros is dangerous

@rwgk rwgk marked this pull request as draft January 10, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants