There are two schools of thought regarding environment variables:
Obviously those two are contradictory and there's no way Steam can do both, so whatever it does, someone is going to be disappointed.
The Steam Runtime has mostly gone with the "user is always right" approach, except in a few specific cases where setting environment variables is functionally necessary to make its containers work. For example, this means that the SDL team can (and do!) use SDL_DYNAMIC_API to force-load a locally-built SDL into Steam games while testing bug fixes.
However, this means that it's up to the user to limit workarounds to the narrowest possible scope where they'll be effective, rather than applying them indiscriminately. Workarounds usually have some important down-sides - if it was safe for them to be the default, they'd be the default already - so the safest way to use them is minimally.
Couldn't load an overriding SDL library. Please fix or remove the SDL_DYNAMIC_API environment variable. Using the default SDL.
For extra warning messages, if you try using Proton/Wine to launch a Windows game that happens to use the Windows version of SDL (Tiny Tina's Assault on Dragon Keep is one that I often use for testing), it will try and fail to load the Linux SDL from $SDL_DYNAMIC_API as though it was a Windows/PE DLL (as well as trying to load the overridden Linux SDL into winedevice.exe to implement gamepad support, which will succeed if given a suitable value). This is because Wine doesn't distinguish between "Linux-world" and "Windows-world" environment variables.
SDL3_DYNAMIC_API=$(realpath /usr/lib/libSDL3.so) SDL_DYNAMIC_API=$(realpath /usr/lib/libSDL2.so)
Why are you setting these environment variables? I would guess that the most likely reason is as a workaround for a non-Steam game that vendors its own outdated copy of SDL (statically linked, or via LD_LIBRARY_PATH or RUNPATH or similar) which you want to replace with your system copy?
If you're doing this as a workaround at that level, I'd recommend setting it in a wrapper script for the individual game(s), instead of globally. Similarly, for Steam games, I'd recommend using Steam's Launch Options feature for individual games that need workarounds, instead of applying workarounds to all of Steam and its recursive process tree, or to the whole OS.
This is also not going to work for 32-bit games, which need to use a 32-bit SDL (if available, it would be in /usr/lib32 on Arch). This word-size issue is why the steam-runtime-launch-options debugging tool doesn't actually set SDL_DYNAMIC_API directly: instead, it sets STEAM_COMPAT_RUNTIME_SDL2 or STEAM_COMPAT_RUNTIME_SDL3, which result in a lower-level component setting SDL_DYNAMIC_API or SDL3_DYNAMIC_API to paths that use the ${LIB} or ${PLATFORM} dynamic string tokens to achieve some limited architecture-independence.
SDL_VIDEO_DRIVER=wayland,x11
Similarly, I would not recommend this. In SDL versions where the default is to prioritize X11 (via Xwayland) higher than native Wayland, that default is there for a reason: if native Wayland was always a better choice than X11 via Xwayland, then the SDL team would already have made it the default.
For Steam users in particular, gameoverlayrenderer.so only works as intended when using X11/GLX, not when using X11/EGL or Wayland/EGL (#8020), so forcing native Wayland to be prioritized will break features like Steam Input.
Similarly, I would not recommend this. In SDL versions where the default is to prioritize X11 (via Xwayland) higher than native Wayland, that default is there for a reason: if native Wayland was always a better choice than X11 via Xwayland, then the SDL team would already have made it the default.
To clarify: Upstream SDL does default to Wayland, but the Steam runtime switches this around as part of working around #8020.
Separately: There are cases where the outer environment variables can clash with containers; for example, an environment may define SDL_VIDEO_DRIVER=wayland but in a Wine environment this doesn't make sense since the only valid driver there is windows. Another example is DOTNET_ROOT which can be defined for a Linux-native .NET SDK installation, but a Wine prefix will inherit this and break any prefix's Windows .NET SDK installation.
I guess the issue boils down to "is there a difference between platform-specific variables and cross-platform variables," which is frustrating just to write down let alone answer, but that's probably because it deserves some kind of answer, no matter how fussy or selective it is at first.
EDIT: Wine Bugzilla report for DOTNET_ROOT https://bugs.winehq.org/show_bug.cgi?id=55544
There are cases where the outer environment variables can clash with containers; for example, an environment may define SDL_VIDEO_DRIVER=wayland but in a Wine environment this doesn't make sense
Wine isn't a container, but yes: a more general description of the issue is that environment variable inheritance can easily cause problems whenever the transition between a higher layer and a lower layer results in changing the execution context so that the environment variable's value is no longer appropriate.
In the Steam Runtime's containers, the change that invalidates (some) environment variables is that the meaning of paths below /lib* and /usr has changed. In Wine, the change that invalidates (some) environment variables is that paths, driver names, etc. are being interpreted as though they were for a Windows program. And when you run a game under Proton, that's Wine inside the Steam Runtime, so both of those problems can happen at the same time.
SDL_VIDEO_DRIVER=waylandx2 2026-07SDL_DYNAMIC_APIx2 2026-07SDL_DYNAMIC_API=$(realpathx2 2026-07SDL_VIDEO_DRIVER=wayland,x11`x1 2026-07STEAM_COMPAT_RUNTIME_SDL2x1 2026-07STEAM_COMPAT_RUNTIME_SDL3x1 2026-07SDL_VIDEO_DRIVERx1 2026-06SDL_VIDEO_DRIVER=wayland,x11x1 2026-06
Your system information
Please describe your issue in as much detail as possible:
I have a few SDL config variables defined in my environment to ensure up-to-date SDL for other applications I run outside of Steam, particularly:
SDL_VIDEO_DRIVERSDL_DYNAMIC_API(SDL2)SDL3_DYNAMIC_API(SDL3)It's clear that the steam runtime might sometimes take these variables into account, looking at the source: https://gitlab.steamos.cloud/steamrt/steam-runtime-tools/-/blob/main/bin/launch-options.py
However, Steam itself does not seem to remove these variables from the environment when it runs, despite the fact that it isolates the environment to remove access to system libraries. So, when adding variables like
SDL_DYNAMIC_APIto the environment, upon launch, Steam shows dialogue boxes and writes to the log with messages like:And this additionally happens for games run via the Steam runtime which use SDL internally, where these dialogue boxes might show up multiple times.
Since Steam is already aware of the various environment variables SDL uses, as evidenced by the Runtime code, it should remove these variables from the environment before it starts, not just when the Steam Runtime is specifically configured to do so with separate scripts.
It's worth mentioning that these dialogue boxes appear to block SDL from starting up until resolved, but will continue to work as normal after that. Steam does not appear to be blocked by this dialogue box (although I wonder what is blocked by it…) but games that use SDL are blocked until dialogue boxes are resolved, sometimes requiring multiple dismissals (presumably because SDL is loaded multiple times for Steam itself, the Runtime, Proton, and the game, for example).
Steps for reproducing this issue:
(note:
SDL_VIDEO_DRIVERis harmless here because both do work, but the dynamic API variables definitely don't, and it's clear from the runtime that Steam may want to turn off all SDL variables if it wants to control the version of SDL available in the runtime)Relevant docs