<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aleksandr Kossarev</title>
    <description>The latest articles on DEV Community by Aleksandr Kossarev (@aleksandr_kossarev_e23623).</description>
    <link>https://dev.to/aleksandr_kossarev_e23623</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2469832%2Ffed4c8f4-77c6-48dc-b44c-bbdac4854a3a.png</url>
      <title>DEV Community: Aleksandr Kossarev</title>
      <link>https://dev.to/aleksandr_kossarev_e23623</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aleksandr_kossarev_e23623"/>
    <language>en</language>
    <item>
      <title>External GPU (eGPU) + NVIDIA Drivers on Linux: Solving the Display Manager Initialization Problem</title>
      <dc:creator>Aleksandr Kossarev</dc:creator>
      <pubDate>Sun, 03 May 2026 14:54:31 +0000</pubDate>
      <link>https://dev.to/aleksandr_kossarev_e23623/external-gpu-egpu-nvidia-drivers-on-linux-solving-the-display-manager-initialization-problem-5gm0</link>
      <guid>https://dev.to/aleksandr_kossarev_e23623/external-gpu-egpu-nvidia-drivers-on-linux-solving-the-display-manager-initialization-problem-5gm0</guid>
      <description>&lt;h1&gt;
  
  
  External GPU (eGPU) + NVIDIA Drivers on Linux: Solving the Display Manager Initialization Problem
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; If your NVIDIA eGPU works in recovery mode but gives a black screen on normal boot, you're missing one critical Xorg option: &lt;code&gt;AllowExternalGpus&lt;/code&gt;. This guide shows how to fix it properly on any X11-based Linux distribution.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Installing NVIDIA drivers on a Linux system with an external GPU (eGPU) connected via Thunderbolt can result in a frustrating black screen instead of your login screen. This issue affects LightDM, SDDM, GDM (X11 session), and other display managers across multiple distributions.&lt;/p&gt;

&lt;p&gt;This guide documents a complete solution tested on real hardware and explains the root cause that official documentation often omits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tested Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardware:&lt;/strong&gt; GEEKOM GT1 Mega (Intel Core Ultra 9 185H with Intel Arc iGPU) + NVIDIA RTX 5060 Ti in Sonnet eGPU Breakaway Box 750ex&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection:&lt;/strong&gt; Thunderbolt 4&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OS:&lt;/strong&gt; Linux Mint 22.3 MATE (applicable to Ubuntu, Fedora, Arch, and any X11-based distribution)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Driver:&lt;/strong&gt; NVIDIA 595 (proprietary)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Symptoms
&lt;/h2&gt;

&lt;p&gt;Before diving into the solution, confirm you're experiencing this specific issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ NVIDIA drivers installed successfully&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;nvidia-smi&lt;/code&gt; works and shows your GPU&lt;/li&gt;
&lt;li&gt;✅ GPU visible in &lt;code&gt;lspci&lt;/code&gt; output&lt;/li&gt;
&lt;li&gt;❌ Black screen instead of login screen on normal boot&lt;/li&gt;
&lt;li&gt;✅ System works normally in recovery mode or without X11&lt;/li&gt;
&lt;li&gt;⚠️ Possible error in dmesg: &lt;code&gt;i915: failed to get ACT after 3000ms&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;❌ Problem persists across different display managers (LightDM, SDDM, GDM in X11 mode)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Root Cause
&lt;/h2&gt;

&lt;p&gt;NVIDIA drivers &lt;strong&gt;intentionally disable external GPUs by default&lt;/strong&gt; as a safety measure to prevent crashes when the Thunderbolt cable is accidentally disconnected.&lt;/p&gt;

&lt;p&gt;Without the &lt;code&gt;AllowExternalGpus&lt;/code&gt; flag, the X11 server attempts to initialize the NVIDIA GPU, receives a denial, and crashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(WW) NVIDIA(GPU-0): This device is an external GPU, but external GPUs have not
(WW) NVIDIA(GPU-0):     been enabled with AllowExternalGpus. Disabling this device
(EE) NVIDIA(0): Failing initialization of X screen
(EE) no screens found
Fatal server error: no screens found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;X11 then attempts to fall back to the Intel iGPU (modesetting driver), but if your monitor is connected only to the eGPU, there are no screens available on the Intel outputs, resulting in a black screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why GNOME/Wayland might work without this fix:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Wayland bypasses X11 and interacts directly with GPUs via KMS (kernel modesetting). NVIDIA drivers don't block KMS access for eGPUs. Display managers using Wayland (like GDM in Wayland mode) will work, while X11-based sessions (LightDM, SDDM, Cinnamon, MATE) will fail.&lt;/p&gt;


&lt;h2&gt;
  
  
  Additional Issue: Boot Race Condition
&lt;/h2&gt;

&lt;p&gt;Even after adding &lt;code&gt;AllowExternalGpus&lt;/code&gt;, you might experience intermittent black screens. This occurs due to timing issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Display manager starts → attempts to launch X11&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nvidia-drm&lt;/code&gt; module hasn't completed initialization (~2–3 seconds)&lt;/li&gt;
&lt;li&gt;Thunderbolt DisplayPort tunnel establishes even later&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is addressed through systemd service synchronization (detailed in Step 4 below).&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Diagnosis
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Check Xorg logs from recovery mode or TTY (Ctrl+Alt+F2):
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"(EE|WW|AllowExternal|no screens|nvidia)"&lt;/span&gt; /var/log/Xorg.0.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you see references to &lt;code&gt;AllowExternalGpus&lt;/code&gt; or &lt;code&gt;no screens found&lt;/code&gt;, you're in the right place.&lt;/p&gt;
&lt;h3&gt;
  
  
  Verify GPU is visible to the system:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvidia-smi
&lt;span class="c"&gt;# Should show GPU with temperature, memory usage, etc.&lt;/span&gt;

lspci | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; nvidia
&lt;span class="c"&gt;# Should list your GPU&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Confirm monitor connection to eGPU:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /sys/class/drm/
&lt;span class="c"&gt;# Look for card0-DP-* or card0-HDMI-* entries&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /sys/class/drm/card0-DP-1/status
&lt;span class="c"&gt;# Should return: connected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: The Critical Fix – AllowExternalGpus
&lt;/h2&gt;

&lt;p&gt;Create or edit the X11 configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/X11/xorg.conf.d/10-nvidia.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Section "ServerLayout"
    Identifier "layout"
    Screen 0 "nvidia"
    Inactive "intel"
EndSection

Section "Device"
    Identifier "nvidia"
    Driver "nvidia"
    Option "PrimaryGPU" "yes"
    Option "AllowExternalGpus" "True"
EndSection

Section "Screen"
    Identifier "nvidia"
    Device "nvidia"
    Option "AllowEmptyInitialConfiguration"
EndSection

Section "Device"
    Identifier "intel"
    Driver "modesetting"
EndSection

Section "Screen"
    Identifier "intel"
    Device "intel"
EndSection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical line:&lt;/strong&gt; &lt;code&gt;Option "AllowExternalGpus" "True"&lt;/code&gt; — nothing works without this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Option "AllowEmptyInitialConfiguration"&lt;/code&gt;&lt;/strong&gt; — allows X11 to start even if the GPU isn't fully initialized when the display manager launches.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Kernel Mode Setting (KMS) Configuration
&lt;/h2&gt;

&lt;p&gt;If not already configured during driver installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify modeset is enabled&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/cmdline | &lt;span class="nb"&gt;grep &lt;/span&gt;nvidia-drm
&lt;span class="c"&gt;# Should show: nvidia-drm.modeset=1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If missing, add to GRUB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/default/grub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Locate &lt;code&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/code&gt; and add parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"quiet splash nvidia-drm.modeset=1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create modprobe configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/modprobe.d/nvidia-kms.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;options nvidia-drm &lt;span class="nv"&gt;modeset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
options nvidia &lt;span class="nv"&gt;NVreg_PreserveVideoMemoryAllocations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;update-grub
&lt;span class="nb"&gt;sudo &lt;/span&gt;update-initramfs &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Boot Race Condition Fix (for stability)
&lt;/h2&gt;

&lt;p&gt;This is optional but eliminates rare black screens on some boots.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPU Wait Script
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/nvidia-egpu-wait.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Wait for NVIDIA GPU to appear in /sys/class/drm&lt;/span&gt;
&lt;span class="nv"&gt;TIMEOUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30
&lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$COUNT&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; &lt;span class="nv"&gt;$TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    if &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /sys/class/drm/ 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"^card[0-9]$"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="c"&gt;# Verify it's NVIDIA, not just Intel&lt;/span&gt;
        &lt;span class="k"&gt;for &lt;/span&gt;card &lt;span class="k"&gt;in&lt;/span&gt; /sys/class/drm/card[0-9]&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
            &lt;/span&gt;&lt;span class="nv"&gt;vendor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$card&lt;/span&gt;&lt;span class="s2"&gt;/device/vendor"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$vendor&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0x10de"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;2  &lt;span class="c"&gt;# Additional pause for TB3 DP tunnel&lt;/span&gt;
                &lt;span class="nb"&gt;exit &lt;/span&gt;0
            &lt;span class="k"&gt;fi
        done
    fi
    &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;1
    &lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;COUNT &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;done
&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0  &lt;span class="c"&gt;# Timeout - continue anyway&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/nvidia-egpu-wait.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Hotplug Script (runs after display manager)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/nvidia-drm-hotplug.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;8
udevadm trigger &lt;span class="nt"&gt;--action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;change &lt;span class="nt"&gt;--subsystem-match&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;drm
udevadm settle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/nvidia-drm-hotplug.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Systemd Service: Wait (runs BEFORE display manager)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/system/nvidia-egpu-wait.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Wait for NVIDIA eGPU initialization&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;bolt.service&lt;/span&gt;
&lt;span class="py"&gt;Before&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;display-manager.service&lt;/span&gt;
&lt;span class="py"&gt;DefaultDependencies&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;oneshot&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/nvidia-egpu-wait.sh&lt;/span&gt;
&lt;span class="py"&gt;RemainAfterExit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="py"&gt;TimeoutSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;35&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;display-manager.service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Systemd Service: Hotplug (runs AFTER display manager)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/system/nvidia-drm-hotplug.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;NVIDIA DRM hotplug trigger after display manager&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;display-manager.service bolt.service&lt;/span&gt;
&lt;span class="py"&gt;Wants&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;display-manager.service&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;oneshot&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/nvidia-drm-hotplug.sh&lt;/span&gt;
&lt;span class="py"&gt;RemainAfterExit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Display Manager Drop-in (LightDM example)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/systemd/system/lightdm.service.d/
&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/system/lightdm.service.d/wait-nvidia-egpu.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Wants&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nvidia-egpu-wait.service&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nvidia-egpu-wait.service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For SDDM, use &lt;code&gt;/etc/systemd/system/sddm.service.d/&lt;/code&gt; instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable Services
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nvidia-egpu-wait.service
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nvidia-drm-hotplug.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5: PRIME Configuration (GPU priority)
&lt;/h2&gt;

&lt;p&gt;On systems with NVIDIA drivers and &lt;code&gt;nvidia-prime&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;prime-select nvidia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;prime-select query
&lt;span class="c"&gt;# Should return: nvidia&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6: Reboot and Verification
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Post-boot verification:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# GPU is active and in use&lt;/span&gt;
nvidia-smi

&lt;span class="c"&gt;# Xorg has no critical errors&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"^(EE|WW)"&lt;/span&gt; /var/log/Xorg.0.log

&lt;span class="c"&gt;# Services completed successfully&lt;/span&gt;
systemctl status nvidia-egpu-wait.service
systemctl status nvidia-drm-hotplug.service

&lt;span class="c"&gt;# NVIDIA is managing the display (not Intel fallback)&lt;/span&gt;
xrandr &lt;span class="nt"&gt;--listproviders&lt;/span&gt;
&lt;span class="c"&gt;# Should show: NVIDIA-0 as primary provider&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Troubleshooting: If Black Screen Persists
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Boot into recovery mode → drop to root shell → check logs:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Main X11 log&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /var/log/Xorg.0.log | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"(EE|WW|AllowExternal|screen)"&lt;/span&gt;

&lt;span class="c"&gt;# Boot journal&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-b&lt;/span&gt; 0 &lt;span class="nt"&gt;-p&lt;/span&gt; err &lt;span class="nt"&gt;--no-pager&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-50&lt;/span&gt;

&lt;span class="c"&gt;# Service status&lt;/span&gt;
systemctl status lightdm nvidia-egpu-wait nvidia-drm-hotplug

&lt;span class="c"&gt;# Initialization sequence&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-b&lt;/span&gt; 0 &lt;span class="nt"&gt;--no-pager&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"(nvidia|drm|lightdm|sddm|bolt)"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-40&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Errors and Solutions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error in Logs&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;AllowExternalGpus&lt;/code&gt; not set → Disabling&lt;/td&gt;
&lt;td&gt;xorg.conf not applied&lt;/td&gt;
&lt;td&gt;Verify path and syntax of &lt;code&gt;/etc/X11/xorg.conf.d/10-nvidia.conf&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;no screens found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;X11 found no monitors&lt;/td&gt;
&lt;td&gt;Confirm monitor connected to eGPU, not Intel outputs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;i915: failed to get ACT after 3000ms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Intel looking for monitor on its outputs&lt;/td&gt;
&lt;td&gt;Normal if monitor not connected to Intel; this is a consequence, not cause&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;NVRM: No NVIDIA GPU found&lt;/code&gt; in dmesg at boot&lt;/td&gt;
&lt;td&gt;Early boot before TB3 initialization&lt;/td&gt;
&lt;td&gt;Normal if only at start; wait-service addresses this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Failing initialization of X screen&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;X11 crashed during GPU init&lt;/td&gt;
&lt;td&gt;Return to Step 2 and verify &lt;code&gt;AllowExternalGpus&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Rollback (if something goes wrong)
&lt;/h2&gt;

&lt;p&gt;From recovery mode or another system (chroot):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Remove our xorg config - X11 reverts to auto-detection&lt;/span&gt;
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; /etc/X11/xorg.conf.d/10-nvidia.conf

&lt;span class="c"&gt;# Or temporarily rename for testing&lt;/span&gt;
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /etc/X11/xorg.conf.d/10-nvidia.conf /etc/X11/xorg.conf.d/10-nvidia.conf.bak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Chroot from another system:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt/target
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/nvme0n1pX /mnt/target  &lt;span class="c"&gt;# replace X with your partition&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /dev /mnt/target/dev
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /proc /mnt/target/proc
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /sys /mnt/target/sys
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /run /mnt/target/run
&lt;span class="nb"&gt;sudo chroot&lt;/span&gt; /mnt/target /bin/bash
&lt;span class="c"&gt;# Make changes...&lt;/span&gt;
&lt;span class="nb"&gt;exit
sudo &lt;/span&gt;umount /mnt/target/dev /mnt/target/proc /mnt/target/sys /mnt/target/run
&lt;span class="nb"&gt;sudo &lt;/span&gt;umount /mnt/target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final Configuration Summary
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Files that should exist after setup:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/X11/xorg.conf.d/10-nvidia.conf          ← primary fix
/etc/modprobe.d/nvidia-kms.conf               ← KMS modeset
/etc/default/grub                             ← nvidia-drm.modeset=1 in cmdline
/usr/local/bin/nvidia-egpu-wait.sh            ← wait script
/usr/local/bin/nvidia-drm-hotplug.sh          ← hotplug script
/etc/systemd/system/nvidia-egpu-wait.service  ← service (Before=DM)
/etc/systemd/system/nvidia-drm-hotplug.service← service (After=DM)
/etc/systemd/system/lightdm.service.d/wait-nvidia-egpu.conf  ← drop-in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key kernel parameters (in /proc/cmdline):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvidia-drm.modeset&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Technical Explanations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why the problem isn't the display manager:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
LightDM, SDDM, and GDM are just wrappers that launch X11. They all use the same X server (&lt;code&gt;/usr/bin/Xorg&lt;/code&gt;). The root cause lies in NVIDIA driver behavior at the X11 level, not in the display manager itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why GNOME/Wayland worked without the fix:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
GNOME defaults to Wayland, which interacts with GPUs via KMS (kernel modesetting) directly, bypassing Xorg. NVIDIA drivers don't block KMS access for eGPUs. Therefore, GDM in Wayland mode worked while LightDM/SSDM (X11) didn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why &lt;code&gt;i915 ACT error&lt;/code&gt; is not the cause:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The Intel iGPU sees that X11 is attempting to use it as a fallback (after NVIDIA rejection) and begins initializing Intel DisplayPort outputs, but the monitor isn't connected to Intel → timeout. This is a consequence of X11 failing with NVIDIA, not the root cause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About Thunderbolt and bolt:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If the eGPU isn't authorized in bolt, it won't appear in the system at all. Check: &lt;code&gt;boltctl list&lt;/code&gt;. If status isn't &lt;code&gt;authorized&lt;/code&gt;, run: &lt;code&gt;sudo boltctl enroll --policy auto &amp;lt;uuid&amp;gt;&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Known Behavior: Boot Delay (30-90 seconds)
&lt;/h2&gt;

&lt;p&gt;On cold boots with eGPU via Thunderbolt, you may experience a delay before the login screen appears. This is normal and relates to sequential initialization:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Thunderbolt authorization (~15 sec)&lt;/li&gt;
&lt;li&gt;NVIDIA driver loading (~20 sec)&lt;/li&gt;
&lt;li&gt;DisplayPort tunnel establishment (~15 sec)&lt;/li&gt;
&lt;li&gt;X11 initialization (~10 sec)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Total:&lt;/strong&gt; 30-60 seconds on modern hardware.&lt;/p&gt;

&lt;p&gt;The systemd services (&lt;code&gt;nvidia-egpu-wait&lt;/code&gt; and &lt;code&gt;nvidia-drm-hotplug&lt;/code&gt;) minimize this delay but can't eliminate it entirely due to Thunderbolt physics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Possible optimizations:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Configure &lt;code&gt;bolt&lt;/code&gt; with &lt;code&gt;auto-enroll&lt;/code&gt; policy&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;nvidia-smi -pm 1&lt;/code&gt; for early GPU "warm-up"&lt;/li&gt;
&lt;li&gt;Disable unused systemd services&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The root cause of black screen issues when using NVIDIA eGPU on Linux isn't the display manager, PRIME configuration, or GRUB parameters. It's a single missing Xorg option: &lt;strong&gt;&lt;code&gt;AllowExternalGpus&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;NVIDIA drivers disable external GPUs by default as a safety measure. Without explicit permission via this flag, X11 initialization fails silently, resulting in a black screen.&lt;/p&gt;

&lt;p&gt;This configuration has been tested extensively and works reliably across multiple distributions. If you're building a Linux workstation with eGPU, this guide can save you hours of troubleshooting.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we learned:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ External GPUs require explicit enablement in Xorg configuration&lt;/li&gt;
&lt;li&gt;✅ Display managers (LightDM, SSDM, GDM in X11) all experience the same issue&lt;/li&gt;
&lt;li&gt;✅ Wayland sessions work because they bypass X11 entirely&lt;/li&gt;
&lt;li&gt;✅ Boot timing issues can be addressed with systemd service synchronization&lt;/li&gt;
&lt;li&gt;✅ The &lt;code&gt;i915 ACT error&lt;/code&gt; is a red herring — a consequence, not the cause&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Questions?&lt;/strong&gt; Feel free to ask in the comments. I'll be monitoring this thread and happy to help troubleshoot your specific configuration.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Aleksandr Kossarev&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Estonia&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Date:&lt;/strong&gt; May 2, 2026&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Hardware:&lt;/strong&gt; GEEKOM GT1 Mega + NVIDIA RTX 5060 Ti (eGPU via Thunderbolt 4)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Project:&lt;/strong&gt; &lt;a href="https://archiscrin.bandcamp.com" rel="noopener noreferrer"&gt;Arche Iscrin&lt;/a&gt; — AI-assisted creative projects&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is based on real-world troubleshooting and testing. All commands and configurations have been verified on actual hardware. Feel free to share this guide with anyone struggling with eGPU setup on Linux.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>nvidia</category>
      <category>egpu</category>
      <category>troubleshooting</category>
    </item>
    <item>
      <title>External GPU (eGPU) + NVIDIA Drivers on Linux: Solving the Display Manager Initialization Problem</title>
      <dc:creator>Aleksandr Kossarev</dc:creator>
      <pubDate>Sun, 03 May 2026 14:54:30 +0000</pubDate>
      <link>https://dev.to/aleksandr_kossarev_e23623/external-gpu-egpu-nvidia-drivers-on-linux-solving-the-display-manager-initialization-problem-1n0p</link>
      <guid>https://dev.to/aleksandr_kossarev_e23623/external-gpu-egpu-nvidia-drivers-on-linux-solving-the-display-manager-initialization-problem-1n0p</guid>
      <description>&lt;h1&gt;
  
  
  External GPU (eGPU) + NVIDIA Drivers on Linux: Solving the Display Manager Initialization Problem
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; If your NVIDIA eGPU works in recovery mode but gives a black screen on normal boot, you're missing one critical Xorg option: &lt;code&gt;AllowExternalGpus&lt;/code&gt;. This guide shows how to fix it properly on any X11-based Linux distribution.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Installing NVIDIA drivers on a Linux system with an external GPU (eGPU) connected via Thunderbolt can result in a frustrating black screen instead of your login screen. This issue affects LightDM, SDDM, GDM (X11 session), and other display managers across multiple distributions.&lt;/p&gt;

&lt;p&gt;This guide documents a complete solution tested on real hardware and explains the root cause that official documentation often omits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tested Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardware:&lt;/strong&gt; GEEKOM GT1 Mega (Intel Core Ultra 9 185H with Intel Arc iGPU) + NVIDIA RTX 5060 Ti in Sonnet eGPU Breakaway Box 750ex&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection:&lt;/strong&gt; Thunderbolt 4&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OS:&lt;/strong&gt; Linux Mint 22.3 MATE (applicable to Ubuntu, Fedora, Arch, and any X11-based distribution)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Driver:&lt;/strong&gt; NVIDIA 595 (proprietary)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Symptoms
&lt;/h2&gt;

&lt;p&gt;Before diving into the solution, confirm you're experiencing this specific issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ NVIDIA drivers installed successfully&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;nvidia-smi&lt;/code&gt; works and shows your GPU&lt;/li&gt;
&lt;li&gt;✅ GPU visible in &lt;code&gt;lspci&lt;/code&gt; output&lt;/li&gt;
&lt;li&gt;❌ Black screen instead of login screen on normal boot&lt;/li&gt;
&lt;li&gt;✅ System works normally in recovery mode or without X11&lt;/li&gt;
&lt;li&gt;⚠️ Possible error in dmesg: &lt;code&gt;i915: failed to get ACT after 3000ms&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;❌ Problem persists across different display managers (LightDM, SDDM, GDM in X11 mode)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Root Cause
&lt;/h2&gt;

&lt;p&gt;NVIDIA drivers &lt;strong&gt;intentionally disable external GPUs by default&lt;/strong&gt; as a safety measure to prevent crashes when the Thunderbolt cable is accidentally disconnected.&lt;/p&gt;

&lt;p&gt;Without the &lt;code&gt;AllowExternalGpus&lt;/code&gt; flag, the X11 server attempts to initialize the NVIDIA GPU, receives a denial, and crashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(WW) NVIDIA(GPU-0): This device is an external GPU, but external GPUs have not
(WW) NVIDIA(GPU-0):     been enabled with AllowExternalGpus. Disabling this device
(EE) NVIDIA(0): Failing initialization of X screen
(EE) no screens found
Fatal server error: no screens found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;X11 then attempts to fall back to the Intel iGPU (modesetting driver), but if your monitor is connected only to the eGPU, there are no screens available on the Intel outputs, resulting in a black screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why GNOME/Wayland might work without this fix:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Wayland bypasses X11 and interacts directly with GPUs via KMS (kernel modesetting). NVIDIA drivers don't block KMS access for eGPUs. Display managers using Wayland (like GDM in Wayland mode) will work, while X11-based sessions (LightDM, SDDM, Cinnamon, MATE) will fail.&lt;/p&gt;


&lt;h2&gt;
  
  
  Additional Issue: Boot Race Condition
&lt;/h2&gt;

&lt;p&gt;Even after adding &lt;code&gt;AllowExternalGpus&lt;/code&gt;, you might experience intermittent black screens. This occurs due to timing issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Display manager starts → attempts to launch X11&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nvidia-drm&lt;/code&gt; module hasn't completed initialization (~2–3 seconds)&lt;/li&gt;
&lt;li&gt;Thunderbolt DisplayPort tunnel establishes even later&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is addressed through systemd service synchronization (detailed in Step 4 below).&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Diagnosis
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Check Xorg logs from recovery mode or TTY (Ctrl+Alt+F2):
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"(EE|WW|AllowExternal|no screens|nvidia)"&lt;/span&gt; /var/log/Xorg.0.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you see references to &lt;code&gt;AllowExternalGpus&lt;/code&gt; or &lt;code&gt;no screens found&lt;/code&gt;, you're in the right place.&lt;/p&gt;
&lt;h3&gt;
  
  
  Verify GPU is visible to the system:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvidia-smi
&lt;span class="c"&gt;# Should show GPU with temperature, memory usage, etc.&lt;/span&gt;

lspci | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; nvidia
&lt;span class="c"&gt;# Should list your GPU&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Confirm monitor connection to eGPU:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /sys/class/drm/
&lt;span class="c"&gt;# Look for card0-DP-* or card0-HDMI-* entries&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /sys/class/drm/card0-DP-1/status
&lt;span class="c"&gt;# Should return: connected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: The Critical Fix – AllowExternalGpus
&lt;/h2&gt;

&lt;p&gt;Create or edit the X11 configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/X11/xorg.conf.d/10-nvidia.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Section "ServerLayout"
    Identifier "layout"
    Screen 0 "nvidia"
    Inactive "intel"
EndSection

Section "Device"
    Identifier "nvidia"
    Driver "nvidia"
    Option "PrimaryGPU" "yes"
    Option "AllowExternalGpus" "True"
EndSection

Section "Screen"
    Identifier "nvidia"
    Device "nvidia"
    Option "AllowEmptyInitialConfiguration"
EndSection

Section "Device"
    Identifier "intel"
    Driver "modesetting"
EndSection

Section "Screen"
    Identifier "intel"
    Device "intel"
EndSection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical line:&lt;/strong&gt; &lt;code&gt;Option "AllowExternalGpus" "True"&lt;/code&gt; — nothing works without this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Option "AllowEmptyInitialConfiguration"&lt;/code&gt;&lt;/strong&gt; — allows X11 to start even if the GPU isn't fully initialized when the display manager launches.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Kernel Mode Setting (KMS) Configuration
&lt;/h2&gt;

&lt;p&gt;If not already configured during driver installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify modeset is enabled&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/cmdline | &lt;span class="nb"&gt;grep &lt;/span&gt;nvidia-drm
&lt;span class="c"&gt;# Should show: nvidia-drm.modeset=1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If missing, add to GRUB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/default/grub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Locate &lt;code&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/code&gt; and add parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"quiet splash nvidia-drm.modeset=1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create modprobe configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/modprobe.d/nvidia-kms.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="n"&gt;nvidia&lt;/span&gt;-&lt;span class="n"&gt;drm&lt;/span&gt; &lt;span class="n"&gt;modeset&lt;/span&gt;=&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="n"&gt;nvidia&lt;/span&gt; &lt;span class="n"&gt;NVreg_PreserveVideoMemoryAllocations&lt;/span&gt;=&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;update-grub
&lt;span class="nb"&gt;sudo &lt;/span&gt;update-initramfs &lt;span class="nt"&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Boot Race Condition Fix (for stability)
&lt;/h2&gt;

&lt;p&gt;This is optional but eliminates rare black screens on some boots.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPU Wait Script
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/nvidia-egpu-wait.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Wait for NVIDIA GPU to appear in /sys/class/drm&lt;/span&gt;
&lt;span class="nv"&gt;TIMEOUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30
&lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$COUNT&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; &lt;span class="nv"&gt;$TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    if &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; /sys/class/drm/ 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"^card[0-9]$"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="c"&gt;# Verify it's NVIDIA, not just Intel&lt;/span&gt;
        &lt;span class="k"&gt;for &lt;/span&gt;card &lt;span class="k"&gt;in&lt;/span&gt; /sys/class/drm/card[0-9]&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
            &lt;/span&gt;&lt;span class="nv"&gt;vendor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$card&lt;/span&gt;&lt;span class="s2"&gt;/device/vendor"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$vendor&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0x10de"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
                &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;2  &lt;span class="c"&gt;# Additional pause for TB3 DP tunnel&lt;/span&gt;
                &lt;span class="nb"&gt;exit &lt;/span&gt;0
            &lt;span class="k"&gt;fi
        done
    fi
    &lt;/span&gt;&lt;span class="nb"&gt;sleep &lt;/span&gt;1
    &lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;COUNT &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;done
&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0  &lt;span class="c"&gt;# Timeout - continue anyway&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/nvidia-egpu-wait.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Hotplug Script (runs after display manager)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/nvidia-drm-hotplug.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;sleep &lt;/span&gt;8
udevadm trigger &lt;span class="nt"&gt;--action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;change &lt;span class="nt"&gt;--subsystem-match&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;drm
udevadm settle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/nvidia-drm-hotplug.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Systemd Service: Wait (runs BEFORE display manager)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/system/nvidia-egpu-wait.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Wait for NVIDIA eGPU initialization&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;bolt.service&lt;/span&gt;
&lt;span class="py"&gt;Before&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;display-manager.service&lt;/span&gt;
&lt;span class="py"&gt;DefaultDependencies&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;oneshot&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/nvidia-egpu-wait.sh&lt;/span&gt;
&lt;span class="py"&gt;RemainAfterExit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="py"&gt;TimeoutSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;35&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;display-manager.service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Systemd Service: Hotplug (runs AFTER display manager)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/system/nvidia-drm-hotplug.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;NVIDIA DRM hotplug trigger after display manager&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;display-manager.service bolt.service&lt;/span&gt;
&lt;span class="py"&gt;Wants&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;display-manager.service&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;oneshot&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/nvidia-drm-hotplug.sh&lt;/span&gt;
&lt;span class="py"&gt;RemainAfterExit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Display Manager Drop-in (LightDM example)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/systemd/system/lightdm.service.d/
&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/systemd/system/lightdm.service.d/wait-nvidia-egpu.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Wants&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nvidia-egpu-wait.service&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nvidia-egpu-wait.service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For SDDM, use &lt;code&gt;/etc/systemd/system/sddm.service.d/&lt;/code&gt; instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable Services
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nvidia-egpu-wait.service
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nvidia-drm-hotplug.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5: PRIME Configuration (GPU priority)
&lt;/h2&gt;

&lt;p&gt;On systems with NVIDIA drivers and &lt;code&gt;nvidia-prime&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;prime-select nvidia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;prime-select query
&lt;span class="c"&gt;# Should return: nvidia&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6: Reboot and Verification
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Post-boot verification:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# GPU is active and in use&lt;/span&gt;
nvidia-smi

&lt;span class="c"&gt;# Xorg has no critical errors&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"^(EE|WW)"&lt;/span&gt; /var/log/Xorg.0.log

&lt;span class="c"&gt;# Services completed successfully&lt;/span&gt;
systemctl status nvidia-egpu-wait.service
systemctl status nvidia-drm-hotplug.service

&lt;span class="c"&gt;# NVIDIA is managing the display (not Intel fallback)&lt;/span&gt;
xrandr &lt;span class="nt"&gt;--listproviders&lt;/span&gt;
&lt;span class="c"&gt;# Should show: NVIDIA-0 as primary provider&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Troubleshooting: If Black Screen Persists
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Boot into recovery mode → drop to root shell → check logs:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Main X11 log&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; /var/log/Xorg.0.log | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"(EE|WW|AllowExternal|screen)"&lt;/span&gt;

&lt;span class="c"&gt;# Boot journal&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-b&lt;/span&gt; 0 &lt;span class="nt"&gt;-p&lt;/span&gt; err &lt;span class="nt"&gt;--no-pager&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-50&lt;/span&gt;

&lt;span class="c"&gt;# Service status&lt;/span&gt;
systemctl status lightdm nvidia-egpu-wait nvidia-drm-hotplug

&lt;span class="c"&gt;# Initialization sequence&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-b&lt;/span&gt; 0 &lt;span class="nt"&gt;--no-pager&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"(nvidia|drm|lightdm|sddm|bolt)"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-40&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Errors and Solutions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error in Logs&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;AllowExternalGpus&lt;/code&gt; not set → Disabling&lt;/td&gt;
&lt;td&gt;xorg.conf not applied&lt;/td&gt;
&lt;td&gt;Verify path and syntax of &lt;code&gt;/etc/X11/xorg.conf.d/10-nvidia.conf&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;no screens found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;X11 found no monitors&lt;/td&gt;
&lt;td&gt;Confirm monitor connected to eGPU, not Intel outputs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;i915: failed to get ACT after 3000ms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Intel looking for monitor on its outputs&lt;/td&gt;
&lt;td&gt;Normal if monitor not connected to Intel; this is a consequence, not cause&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;NVRM: No NVIDIA GPU found&lt;/code&gt; in dmesg at boot&lt;/td&gt;
&lt;td&gt;Early boot before TB3 initialization&lt;/td&gt;
&lt;td&gt;Normal if only at start; wait-service addresses this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Failing initialization of X screen&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;X11 crashed during GPU init&lt;/td&gt;
&lt;td&gt;Return to Step 2 and verify &lt;code&gt;AllowExternalGpus&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Rollback (if something goes wrong)
&lt;/h2&gt;

&lt;p&gt;From recovery mode or another system (chroot):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Remove our xorg config - X11 reverts to auto-detection&lt;/span&gt;
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; /etc/X11/xorg.conf.d/10-nvidia.conf

&lt;span class="c"&gt;# Or temporarily rename for testing&lt;/span&gt;
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /etc/X11/xorg.conf.d/10-nvidia.conf /etc/X11/xorg.conf.d/10-nvidia.conf.bak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Chroot from another system:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt/target
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount /dev/nvme0n1pX /mnt/target  &lt;span class="c"&gt;# replace X with your partition&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /dev /mnt/target/dev
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /proc /mnt/target/proc
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /sys /mnt/target/sys
&lt;span class="nb"&gt;sudo &lt;/span&gt;mount &lt;span class="nt"&gt;--bind&lt;/span&gt; /run /mnt/target/run
&lt;span class="nb"&gt;sudo chroot&lt;/span&gt; /mnt/target /bin/bash
&lt;span class="c"&gt;# Make changes...&lt;/span&gt;
&lt;span class="nb"&gt;exit
sudo &lt;/span&gt;umount /mnt/target/dev /mnt/target/proc /mnt/target/sys /mnt/target/run
&lt;span class="nb"&gt;sudo &lt;/span&gt;umount /mnt/target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final Configuration Summary
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Files that should exist after setup:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/X11/xorg.conf.d/10-nvidia.conf          ← primary fix
/etc/modprobe.d/nvidia-kms.conf               ← KMS modeset
/etc/default/grub                             ← nvidia-drm.modeset=1 in cmdline
/usr/local/bin/nvidia-egpu-wait.sh            ← wait script
/usr/local/bin/nvidia-drm-hotplug.sh          ← hotplug script
/etc/systemd/system/nvidia-egpu-wait.service  ← service (Before=DM)
/etc/systemd/system/nvidia-drm-hotplug.service← service (After=DM)
/etc/systemd/system/lightdm.service.d/wait-nvidia-egpu.conf  ← drop-in
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key kernel parameters (in /proc/cmdline):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvidia-drm.modeset&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Technical Explanations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why the problem isn't the display manager:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
LightDM, SDDM, and GDM are just wrappers that launch X11. They all use the same X server (&lt;code&gt;/usr/bin/Xorg&lt;/code&gt;). The root cause lies in NVIDIA driver behavior at the X11 level, not in the display manager itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why GNOME/Wayland worked without the fix:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
GNOME defaults to Wayland, which interacts with GPUs via KMS (kernel modesetting) directly, bypassing Xorg. NVIDIA drivers don't block KMS access for eGPUs. Therefore, GDM in Wayland mode worked while LightDM/SSDM (X11) didn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why &lt;code&gt;i915 ACT error&lt;/code&gt; is not the cause:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The Intel iGPU sees that X11 is attempting to use it as a fallback (after NVIDIA rejection) and begins initializing Intel DisplayPort outputs, but the monitor isn't connected to Intel → timeout. This is a consequence of X11 failing with NVIDIA, not the root cause.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About Thunderbolt and bolt:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If the eGPU isn't authorized in bolt, it won't appear in the system at all. Check: &lt;code&gt;boltctl list&lt;/code&gt;. If status isn't &lt;code&gt;authorized&lt;/code&gt;, run: &lt;code&gt;sudo boltctl enroll --policy auto &amp;lt;uuid&amp;gt;&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Known Behavior: Boot Delay (30-90 seconds)
&lt;/h2&gt;

&lt;p&gt;On cold boots with eGPU via Thunderbolt, you may experience a delay before the login screen appears. This is normal and relates to sequential initialization:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Thunderbolt authorization (~15 sec)&lt;/li&gt;
&lt;li&gt;NVIDIA driver loading (~20 sec)&lt;/li&gt;
&lt;li&gt;DisplayPort tunnel establishment (~15 sec)&lt;/li&gt;
&lt;li&gt;X11 initialization (~10 sec)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Total:&lt;/strong&gt; 30-60 seconds on modern hardware.&lt;/p&gt;

&lt;p&gt;The systemd services (&lt;code&gt;nvidia-egpu-wait&lt;/code&gt; and &lt;code&gt;nvidia-drm-hotplug&lt;/code&gt;) minimize this delay but can't eliminate it entirely due to Thunderbolt physics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Possible optimizations:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Configure &lt;code&gt;bolt&lt;/code&gt; with &lt;code&gt;auto-enroll&lt;/code&gt; policy&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;nvidia-smi -pm 1&lt;/code&gt; for early GPU "warm-up"&lt;/li&gt;
&lt;li&gt;Disable unused systemd services&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The root cause of black screen issues when using NVIDIA eGPU on Linux isn't the display manager, PRIME configuration, or GRUB parameters. It's a single missing Xorg option: &lt;strong&gt;&lt;code&gt;AllowExternalGpus&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;NVIDIA drivers disable external GPUs by default as a safety measure. Without explicit permission via this flag, X11 initialization fails silently, resulting in a black screen.&lt;/p&gt;

&lt;p&gt;This configuration has been tested extensively and works reliably across multiple distributions. If you're building a Linux workstation with eGPU, this guide can save you hours of troubleshooting.&lt;/p&gt;

&lt;h3&gt;
  
  
  What we learned:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ External GPUs require explicit enablement in Xorg configuration&lt;/li&gt;
&lt;li&gt;✅ Display managers (LightDM, SSDM, GDM in X11) all experience the same issue&lt;/li&gt;
&lt;li&gt;✅ Wayland sessions work because they bypass X11 entirely&lt;/li&gt;
&lt;li&gt;✅ Boot timing issues can be addressed with systemd service synchronization&lt;/li&gt;
&lt;li&gt;✅ The &lt;code&gt;i915 ACT error&lt;/code&gt; is a red herring — a consequence, not the cause&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Questions?&lt;/strong&gt; Feel free to ask in the comments. I'll be monitoring this thread and happy to help troubleshoot your specific configuration.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Aleksandr Kossarev&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Estonia&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Date:&lt;/strong&gt; May 2, 2026&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Hardware:&lt;/strong&gt; GEEKOM GT1 Mega + NVIDIA RTX 5060 Ti (eGPU via Thunderbolt 4)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Project:&lt;/strong&gt; &lt;a href="https://archiscrin.bandcamp.com" rel="noopener noreferrer"&gt;Arche Iscrin&lt;/a&gt; — AI-assisted creative projects&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is based on real-world troubleshooting and testing. All commands and configurations have been verified on actual hardware. Feel free to share this guide with anyone struggling with eGPU setup on Linux.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>nvidia</category>
      <category>egpu</category>
      <category>troubleshooting</category>
    </item>
    <item>
      <title>Building AI That Doesn't Lose Its Mind: A Universal Architecture for Stable Memory Systems</title>
      <dc:creator>Aleksandr Kossarev</dc:creator>
      <pubDate>Tue, 06 Jan 2026 15:21:13 +0000</pubDate>
      <link>https://dev.to/aleksandr_kossarev_e23623/building-ai-that-doesnt-lose-its-mind-a-universal-architecture-for-stable-memory-systems-3naf</link>
      <guid>https://dev.to/aleksandr_kossarev_e23623/building-ai-that-doesnt-lose-its-mind-a-universal-architecture-for-stable-memory-systems-3naf</guid>
      <description>&lt;h2&gt;
  
  
  From Problem to Concept
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This article continues the discussion of memory recursion in AI systems, as described in &lt;a href="https://dev.to/aleksandr_kossarev_e23623/the-day-my-ai-started-talking-to-itself-and-the-math-behind-why-it-always-happens-2ik6"&gt;The Day My AI Started Talking to Itself&lt;/a&gt;. If you haven't read it yet, we recommend starting there — it covers the problem itself and its mathematical inevitability.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once it became clear that memory recursion isn't a specific bug but a fundamental architectural problem, the question arose: &lt;strong&gt;how do we actually solve it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simple solutions like "just apply decay" or "lower the weight of AI outputs" turned out to be half-measures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decay kills important memories along with noise&lt;/li&gt;
&lt;li&gt;Lowering weights turns AI into a "mirror" of the user&lt;/li&gt;
&lt;li&gt;Deleting old data deprives the system of long-term memory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We needed something more fundamental. Not a "patch," but an &lt;strong&gt;architectural principle&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclaimer: What This Article Is About
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Important to understand:&lt;/strong&gt; This article is not the ultimate truth. It's a reflection on a possible concept, an attempt to formulate universal principles for preventing recursion in AI systems with multi-layered memory.&lt;/p&gt;

&lt;p&gt;The principles proposed here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✓ Are based on analysis of real recursion cases&lt;/li&gt;
&lt;li&gt;✓ Are inspired by how human consciousness works&lt;/li&gt;
&lt;li&gt;✓ Have mathematical justification&lt;/li&gt;
&lt;li&gt;✓ Are practically implementable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this is &lt;strong&gt;not the only possible solution&lt;/strong&gt;. Rather, it's a starting point for reflection and experimentation.&lt;/p&gt;

&lt;p&gt;Nevertheless, we believe these principles are significantly better than many current approaches and have every right to exist and be implemented.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Key Idea: Learning from the Human Brain
&lt;/h2&gt;

&lt;p&gt;The question wasn't &lt;strong&gt;why&lt;/strong&gt; this happens (that's already clear), but &lt;strong&gt;how to prevent it without losing system utility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And here an unexpected source of inspiration helped us: human consciousness.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Human Brain's Solution
&lt;/h2&gt;

&lt;p&gt;Think about how a healthy human mind works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;There's a core identity&lt;/strong&gt; - your personality, values, fundamental beliefs&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These DON'T change from daily interactions&lt;/li&gt;
&lt;li&gt;They filter and interpret new information&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;There's verified knowledge&lt;/strong&gt; - facts you're confident about&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These change slowly, with evidence&lt;/li&gt;
&lt;li&gt;They're resistant to casual contradictions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;There's working memory&lt;/strong&gt; - current context, recent conversations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These change rapidly&lt;/li&gt;
&lt;li&gt;They fade naturally when no longer relevant&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;There's critical thinking&lt;/strong&gt; - new information is evaluated&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it contradict what I know?&lt;/li&gt;
&lt;li&gt;Is the source trustworthy?&lt;/li&gt;
&lt;li&gt;Am I thinking about this too much?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Humans don't get stuck in loops because we have layers with different rules.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture: Three-Layer Memory
&lt;/h2&gt;

&lt;p&gt;Here's the proposed approach that theoretically should prevent recursion while preserving useful memory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐
│  LAYER 1: IDENTITY CORE                             │
│  • System principles and behavior patterns          │
│  • Meta-principles: diversity, relevance, honesty   │
│  • Weight: ALWAYS 1.0                               │
│  • Never changes from interactions                  │
└─────────────────────────────────────────────────────┘
            ↓ interprets everything through this lens
┌─────────────────────────────────────────────────────┐
│  LAYER 2: VALIDATED KNOWLEDGE                       │
│  • User preferences and facts                       │
│  • Confirmed through multiple interactions          │
│  • Weight: 0.8-1.0                                  │
│  • Slow temporal decay (6-12 month half-life)      │
│  • Must be consistent with Layer 1                  │
└─────────────────────────────────────────────────────┘
            ↓ provides context for
┌─────────────────────────────────────────────────────┐
│  LAYER 3: CONTEXTUAL MEMORY                         │
│  • Recent conversations and AI outputs              │
│  • Weight: 0.3-0.6                                  │
│  • Fast temporal decay (1-2 week half-life)        │
│  • Requires validation to move to Layer 2          │
└─────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why This Should Work
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Layer 1 (Identity)&lt;/strong&gt; acts as an attractor—the system always gravitates back toward its core principles, preventing drift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2 (Knowledge)&lt;/strong&gt; stores what matters long-term, but only after validation. AI outputs rarely reach here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3 (Context)&lt;/strong&gt; is disposable. AI outputs start here with low weight and naturally fade unless confirmed by external sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six Universal Principles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Principle 1: Asymmetric Source Trust
&lt;/h3&gt;

&lt;p&gt;Not all sources are equal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;SOURCE_TRUST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USER_EXPLICIT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# User directly stated
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USER_IMPLICIT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Inferred from behavior
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EXTERNAL_VERIFIED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Verified external data
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI_OUTPUT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Own generation
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI_RECURSIVE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Nth-order generation
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical:&lt;/strong&gt; This is built into the architecture, not a config option.&lt;/p&gt;

&lt;h3&gt;
  
  
  Principle 2: Temporal Dynamics with Exceptions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;temporal_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age_days&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Facts and preferences don't decay
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FACT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PREFERENCE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IDENTITY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;

    &lt;span class="c1"&gt;# Recent confirmations reset decay
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;has_recent_confirmation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;

    &lt;span class="c1"&gt;# Layer 3: fast decay (7 day half-life)
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layer&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;age_days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Layer 2: slow decay (180 day half-life)
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layer&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.004&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;age_days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key insight:&lt;/strong&gt; Decay applies to context, not to knowledge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Principle 3: Contradiction Detection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;integrate_memory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Check 1: Contradicts identity?
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;contradicts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;identity_core&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI_OUTPUT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# User contradicts identity - note but don't integrate
&lt;/span&gt;            &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
            &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

    &lt;span class="c1"&gt;# Check 2: Contradicts validated knowledge?
&lt;/span&gt;    &lt;span class="n"&gt;conflicts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;find_conflicts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;layer2_memories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;conflicts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_trust&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;conflicts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_trust&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;update_knowledge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conflicts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disputed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
            &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

    &lt;span class="c1"&gt;# Check 3: Recursion pattern?
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_recurring_theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI_OUTPUT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;
        &lt;span class="nf"&gt;flag_for_review&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Principle 4: Homeostatic Regulation
&lt;/h3&gt;

&lt;p&gt;The system automatically corrects itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;regulate_system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window_days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Measure theme diversity
&lt;/span&gt;    &lt;span class="n"&gt;theme_entropy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shannon_entropy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;recent_themes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window_days&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Detect dominant patterns
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_themes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;frequency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total_interactions&lt;/span&gt;
        &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;num_themes&lt;/span&gt;

        &lt;span class="c1"&gt;# Theme appears 3x more than expected?
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;frequency&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_majority&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI_OUTPUT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# This is recursion - suppress
&lt;/span&gt;                &lt;span class="nf"&gt;suppress_theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Legitimate interest - but diversify
&lt;/span&gt;                &lt;span class="nf"&gt;boost_alternative_themes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Measure drift from identity
&lt;/span&gt;    &lt;span class="n"&gt;identity_distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;measure_drift_from_core&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;identity_distance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;apply_identity_restoration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This function can run automatically every few days&lt;/strong&gt;, catching problems before users notice them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Principle 5: Gradient-Based Retrieval
&lt;/h3&gt;

&lt;p&gt;Memory retrieval considers multiple factors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_memories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;all_memories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Base relevance
&lt;/span&gt;        &lt;span class="n"&gt;relevance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Source modifier
&lt;/span&gt;        &lt;span class="n"&gt;source_mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_trust&lt;/span&gt;

        &lt;span class="c1"&gt;# Layer modifier
&lt;/span&gt;        &lt;span class="n"&gt;layer_mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Temporal modifier (with exceptions)
&lt;/span&gt;        &lt;span class="n"&gt;temporal_mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;temporal_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age_days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Anti-spam (retrieval frequency)
&lt;/span&gt;        &lt;span class="n"&gt;retrieval_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrievals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;anti_spam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;retrieval_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Identity alignment
&lt;/span&gt;        &lt;span class="n"&gt;identity_alignment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;identity_core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Combined score
&lt;/span&gt;        &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;relevance&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
            &lt;span class="n"&gt;source_mod&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
            &lt;span class="n"&gt;layer_mod&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
            &lt;span class="n"&gt;temporal_mod&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
            &lt;span class="n"&gt;anti_spam&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;identity_alignment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Diversity-aware selection
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;select_diverse_top_k&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;diversity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Principle 6: Monitoring Dashboard
&lt;/h3&gt;

&lt;p&gt;To control system effectiveness, the following set of metrics is proposed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────────────────────────────┐
│ AI Memory Health Dashboard           │
├──────────────────────────────────────┤
│ Shannon Entropy: 2.4 ✓               │
│   Target: &amp;gt; 2.0                      │
│                                      │
│ Identity Distance: 0.12 ✓            │
│   Target: &amp;lt; 0.20                     │
│                                      │
│ Self-Reference Rate: 8% ✓            │
│   Target: &amp;lt; 15%                      │
│                                      │
│ Layer Distribution:                  │
│   Layer 1: 5% ✓                      │
│   Layer 2: 25% ✓                     │
│   Layer 3: 70% ✓                     │
│                                      │
│ Recent Interventions:                │
│   Theme "balance" suppressed         │
│   Reason: 35% frequency, AI source   │
│   Date: 2 days ago                   │
└──────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementation Checklist
&lt;/h2&gt;

&lt;p&gt;If you decide to try implementing this concept in your system, here are the main steps (without strict timeframes — it all depends on your architecture):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Infrastructure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Add &lt;code&gt;layer&lt;/code&gt; field to memory records (1, 2, or 3)&lt;/li&gt;
&lt;li&gt;[ ] Add &lt;code&gt;source&lt;/code&gt; field (&lt;code&gt;USER&lt;/code&gt;, &lt;code&gt;AI_OUTPUT&lt;/code&gt;, &lt;code&gt;EXTERNAL&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;[ ] Add &lt;code&gt;source_trust&lt;/code&gt; calculation&lt;/li&gt;
&lt;li&gt;[ ] Implement basic temporal decay for Layer 3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Core Logic:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Implement three-layer storage logic&lt;/li&gt;
&lt;li&gt;[ ] Add contradiction detection&lt;/li&gt;
&lt;li&gt;[ ] Modify retrieval to use gradient scoring&lt;/li&gt;
&lt;li&gt;[ ] Create Identity Core definition&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Self-Regulation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Implement theme frequency tracking&lt;/li&gt;
&lt;li&gt;[ ] Add homeostatic regulation (periodic run)&lt;/li&gt;
&lt;li&gt;[ ] Create monitoring dashboard&lt;/li&gt;
&lt;li&gt;[ ] Set up anomaly alerts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fine-Tuning:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Adjust decay rates based on observations&lt;/li&gt;
&lt;li&gt;[ ] Fine-tune thresholds&lt;/li&gt;
&lt;li&gt;[ ] Test edge cases&lt;/li&gt;
&lt;li&gt;[ ] Document system behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Expected Results
&lt;/h2&gt;

&lt;p&gt;This architecture is a conceptual development based on analysis of recursion problems in existing systems. Here's what can be expected from its implementation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current systems (with recursion):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Theme diversity: 0.28 (low)
Self-reference rate: 35%
User complaints: Weekly
Memory useful lifespan: ~2 weeks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected results (with proposed architecture):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Theme diversity: 0.6+ (healthy)
Self-reference rate: &amp;lt; 10%
User complaints: Significant reduction
Memory useful lifespan: Months to years
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;These projections are based on theoretical analysis and require practical validation.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Key Insight
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The human brain doesn't treat all information equally.&lt;/strong&gt; It has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A stable core (personality)&lt;/li&gt;
&lt;li&gt;Trusted knowledge (facts)&lt;/li&gt;
&lt;li&gt;Disposable context (working memory)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your AI needs the same structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Doesn't this make the AI less "intelligent"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: No—it makes it more stable. Intelligence without stability is insanity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What if the user wants to change the AI's behavior?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Layer 2 can be updated with validated user input. Layer 1 remains stable but can be manually adjusted by developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do I define the Identity Core?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Start with meta-principles: be helpful, be diverse, be accurate, be relevant. Refine based on your use case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does this work with vector databases?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Yes! The layer/source/weight fields work with any storage system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What about very large memory systems (millions of entries)?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Layer 3 can be aggressively pruned. Layer 2 grows slowly. Layer 1 is tiny. Theoretically, the architecture should scale well, but this requires validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;AI memory recursion isn't a bug—it's a mathematical inevitability in systems without thoughtful architecture.&lt;/p&gt;

&lt;p&gt;We've proposed an approach based on structuring memory like a healthy mind—with different layers and rules for each. The six principles described above form a framework that may help prevent recursion.&lt;/p&gt;

&lt;p&gt;But let's repeat once more: &lt;strong&gt;this is a concept that requires validation&lt;/strong&gt;. Perhaps in practice nuances will emerge that we haven't considered. Perhaps someone will find a more elegant solution.&lt;/p&gt;

&lt;p&gt;We're not seeking the status of "the only correct approach." Rather, we want to start a discussion about how to properly design memory for AI systems. If this concept proves useful even just as a starting point—we'll consider the task accomplished.&lt;/p&gt;

&lt;p&gt;Going to try implementing it? Found weak spots? Came up with improvements? Share your experience—that's the only way we can move forward.&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Original discussion on memory recursion: &lt;a href="https://dev.to/aleksandr_kossarev_e23623/the-day-my-ai-started-talking-to-itself-and-the-math-behind-why-it-always-happens-2ik6"&gt;The Day My AI Started Talking to Itself&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Shannon Entropy in information systems&lt;/li&gt;
&lt;li&gt;Attractor theory in dynamical systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's Discuss
&lt;/h2&gt;

&lt;p&gt;Have you encountered memory recursion in your AI projects? What patterns have you noticed? Share your experiences in the comments!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #ai #architecture #memory #machinelearning #systemdesign&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About this article:&lt;/strong&gt;  The principles are designed to be universal and potentially applicable to any AI system with persistent memory, regardless of the underlying technology stack. The concept requires practical validation and can be adapted to specific requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #ai #architecture #memory #systemdesign&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>memory</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>The Day My AI Started Talking to Itself (And the Math Behind Why It Always Happens)</title>
      <dc:creator>Aleksandr Kossarev</dc:creator>
      <pubDate>Tue, 06 Jan 2026 11:21:00 +0000</pubDate>
      <link>https://dev.to/aleksandr_kossarev_e23623/the-day-my-ai-started-talking-to-itself-and-the-math-behind-why-it-always-happens-2ik6</link>
      <guid>https://dev.to/aleksandr_kossarev_e23623/the-day-my-ai-started-talking-to-itself-and-the-math-behind-why-it-always-happens-2ik6</guid>
      <description>&lt;p&gt;Have you ever built an AI assistant with memory, felt proud of it, then watched in horror as it slowly went insane?&lt;/p&gt;

&lt;p&gt;Not "crashed" insane. Not "threw an exception" insane. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subtly, gradually, conversationally insane.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 1: Everything's Fine ✓
&lt;/h2&gt;

&lt;p&gt;Your AI mentions "finding balance in life" three times. Reasonable, right? It's good advice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 4: Hmm, That's Weird ⚠️
&lt;/h2&gt;

&lt;p&gt;"Balance" comes up 12 times. Still... maybe you've been stressed?&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 8: Houston, We Have a Problem 🔥
&lt;/h2&gt;

&lt;p&gt;Your AI has mentioned "balance" &lt;strong&gt;35 times&lt;/strong&gt;. In responses about coffee. About code reviews. About literally everything.&lt;/p&gt;

&lt;p&gt;You check the logs. The AI isn't broken. It's &lt;em&gt;working perfectly&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's when you realize:&lt;/strong&gt; Your AI is reading its own outputs as "important memories."&lt;/p&gt;

&lt;p&gt;It's stuck in an echo chamber. &lt;strong&gt;Talking to itself.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Universal Law Nobody Tells You
&lt;/h2&gt;

&lt;p&gt;Here's what took me days to understand:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Every AI system with memory WILL eventually develop recursion.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Not "might." Not "could." &lt;strong&gt;WILL.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This isn't a bug in your code. It's not your framework. It's not your vector database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's mathematics.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Recursion Equation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;P(memory_retrieved) = (Importance × Relevance) / Time_decay

If Time_decay = 0 → P grows unbounded → Recursion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In plain English: If old memories keep their importance forever, they'll dominate all future responses. Forever.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Happens to EVERYONE
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Iron Law of Memory Systems:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ANY system where:
  1. Past outputs are stored ✓
  2. Past outputs can be retrieved ✓  
  3. Past outputs influence future outputs ✓

WILL eventually develop recursion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Language doesn't matter (Python, JavaScript, Rust).&lt;br&gt;&lt;br&gt;
AI model doesn't matter (GPT, Claude, LLaMA, custom).&lt;br&gt;&lt;br&gt;
Architecture doesn't matter (SQL, vector DB, graph).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem is architectural, not technical.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  How I Discovered This (The Hard Way)
&lt;/h2&gt;

&lt;p&gt;I was building Archik — an AI assistant with long-term memory. The kind that remembers your preferences, past conversations, decisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Dream:&lt;/strong&gt; An AI that gets smarter over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Reality:&lt;/strong&gt; An AI that became increasingly... weird.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Symptoms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Same phrases appearing again and again&lt;/li&gt;
&lt;li&gt;Technical reports showing up in casual conversation&lt;/li&gt;
&lt;li&gt;Old discussions dominating new topics&lt;/li&gt;
&lt;li&gt;User complaints: "You keep bringing that up!"&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  The Diagnosis
&lt;/h3&gt;

&lt;p&gt;I analyzed 5,000+ messages in the database. What I found shocked me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My AI's own technical reports had importance scores of 0.95&lt;/strong&gt; (nearly maximum).&lt;/p&gt;

&lt;p&gt;Why? They were long (2000+ characters), detailed, and mentioned important keywords.&lt;/p&gt;

&lt;p&gt;The system saw them as "valuable memories."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But they were just debug output.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every time the AI retrieved context, these reports came back. The AI read them, incorporated their style, and produced &lt;em&gt;more reports in the same style&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Which got saved. With high importance. Which got retrieved again...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classic recursion loop.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Weight-Decay-Context Triangle
&lt;/h2&gt;

&lt;p&gt;Every memory system operates in three dimensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        IMPORTANCE (Weight)
               ↑
               |
               |
    OLD ←──────┼──────→ NEW (Time)
               |
               |
               ↓
        RETRIEVAL (Context)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Healthy System:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;New memories have moderate weight&lt;/li&gt;
&lt;li&gt;Old memories decay over time
&lt;/li&gt;
&lt;li&gt;Context balances past and present&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Recursive System:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Old memories keep high weight&lt;/li&gt;
&lt;li&gt;No temporal decay&lt;/li&gt;
&lt;li&gt;Past dominates present&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The math is simple:&lt;/strong&gt; Static importance + No time decay = Guaranteed recursion.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Three-Layer Defense
&lt;/h2&gt;

&lt;p&gt;After debugging this for days, I realized you need &lt;strong&gt;multiple layers of protection&lt;/strong&gt;. No single fix works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: Dynamic Importance (At Write Time)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Long messages automatically get high importance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Penalize length, categorize content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_importance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;

    &lt;span class="c1"&gt;# Penalize excessive length
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;  &lt;span class="c1"&gt;# Technical report? Lower importance
&lt;/span&gt;
    &lt;span class="c1"&gt;# Type matters
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_apology&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;  &lt;span class="c1"&gt;# Apologies are transient
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_user_preference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;  &lt;span class="c1"&gt;# Preferences are critical
&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Technical reports no longer dominate memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2: Temporal Decay (Over Time)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; 6-month-old memories have same weight as yesterday's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Exponential decay based on age.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_decay&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;days_old&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_favorite&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# 5% decay per day
&lt;/span&gt;            &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;importance&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;days_old&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Archive if too low
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;importance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;archive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Old memories fade naturally, new stay relevant.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3: Automated Detection (Periodic Monitoring)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Recursion develops slowly. You won't notice until it's bad.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Automated pattern detection every 3 days.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;detect_recursion&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_last_50_messages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;themes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_themes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frequency&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;frequency&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Appears in &amp;gt;35% of messages
&lt;/span&gt;            &lt;span class="c1"&gt;# Find and lower importance of old messages
&lt;/span&gt;            &lt;span class="n"&gt;old_messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;find_old_messages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;old_messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;importance&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;

            &lt;span class="nf"&gt;log_intervention&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frequency&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Catches problems before user complains.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Results: Before and After
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before Fix:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analysis of 5,000 messages:
- "balance" mentioned: 35 times/week
- Technical reports in context: 70%
- User satisfaction: Frustrated
- Diversity score: 0.28 (low)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  After Fix:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Same system, 2 weeks later:
- "balance" mentioned: 3 times/week  
- Technical reports in context: 5%
- User satisfaction: Happy
- Diversity score: 0.62 (healthy)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Time to implement:&lt;/strong&gt; ~3 hours of focused work.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Lines of code changed:&lt;/strong&gt; ~200.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Impact:&lt;/strong&gt; System completely stable.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Dashboard That Saved Me
&lt;/h2&gt;

&lt;p&gt;You can't fix what you can't measure. Here's what I monitor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────┐
│ AI Memory Health Dashboard          │
├─────────────────────────────────────┤
│ Total Messages: 5,247               │
│ Avg Importance: 0.38 ✓              │
│                                     │
│ Distribution:                       │
│   Low (0-0.3):    42% ✓            │
│   Medium (0.3-0.5): 33% ✓          │
│   High (0.5-1.0):  25% ✓           │
│                                     │
│ Retrieval Stats:                    │
│   Never retrieved:  68% ✓           │
│   Retrieved 1-5x:   24% ✓           │
│   Retrieved 5+:     8% ⚠            │
│                                     │
│ Recent Detections:                  │
│   Issues found: 0 ✓                 │
│   Last scan: 2 days ago             │
└─────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Target metrics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average importance: 0.35-0.40&lt;/li&gt;
&lt;li&gt;Never retrieved: 60-70%&lt;/li&gt;
&lt;li&gt;Theme diversity: &amp;gt;0.4&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these drift, recursion is developing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Key Insights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Recursion is Mathematical, Not Technical
&lt;/h3&gt;

&lt;p&gt;You can't "fix" it with a patch. It's an architectural property of systems with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory storage&lt;/li&gt;
&lt;li&gt;Retrieval mechanisms
&lt;/li&gt;
&lt;li&gt;Feedback loops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Design for decay from day one.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Importance Must Be Dynamic
&lt;/h3&gt;

&lt;p&gt;Static importance scores &lt;em&gt;guarantee&lt;/em&gt; eventual recursion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Importance should depend on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Content type&lt;/li&gt;
&lt;li&gt;Age&lt;/li&gt;
&lt;li&gt;Retrieval frequency&lt;/li&gt;
&lt;li&gt;User feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. You Need Automated Monitoring
&lt;/h3&gt;

&lt;p&gt;Humans can't detect gradual recursion. It develops over weeks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Periodic automated scans with alerts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your Checklist: Is Your AI at Risk?
&lt;/h2&gt;

&lt;p&gt;Ask yourself three questions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Do old memories keep their importance forever?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If yes: You WILL develop recursion eventually&lt;/li&gt;
&lt;li&gt;Fix: Implement temporal decay&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Do long messages get high importance automatically?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If yes: Technical outputs will dominate&lt;/li&gt;
&lt;li&gt;Fix: Penalize length, categorize content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Are you monitoring for repetitive patterns?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If no: Recursion is developing silently right now&lt;/li&gt;
&lt;li&gt;Fix: Add automated detection&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;As we build more AI systems with memory (and we all are), this pattern will become more common.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The good news:&lt;/strong&gt; It's preventable. Solvable. With relatively simple architecture changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The bad news:&lt;/strong&gt; Most developers won't realize they have recursion until users complain.&lt;/p&gt;

&lt;p&gt;Don't be that developer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Want the Full Technical Deep-Dive?
&lt;/h2&gt;

&lt;p&gt;This article covers the key insights and practical solutions. If you want the complete technical architecture, all the code patterns, edge cases, and scaling strategies:&lt;/p&gt;

&lt;p&gt;📄 &lt;strong&gt;&lt;a href="https://gist.github.com/alexk202/f52f972ea69f88e4d30ab14b5d7a2ae3" rel="noopener noreferrer"&gt;Full PSP on GitHub Gist&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5-layer defense architecture&lt;/li&gt;
&lt;li&gt;Detailed code examples&lt;/li&gt;
&lt;li&gt;Case studies from production&lt;/li&gt;
&lt;li&gt;Monitoring and metrics guide&lt;/li&gt;
&lt;li&gt;Common pitfalls and solutions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Let's Discuss
&lt;/h2&gt;

&lt;p&gt;Have you encountered memory recursion in your AI systems? What was your "aha!" moment?&lt;/p&gt;

&lt;p&gt;Or are you building something with memory right now? I'm happy to discuss architecture approaches in the comments! 👇&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;About the writing process:&lt;/strong&gt; I documented this using Claude AI as my technical writing assistant. English isn't my first language, and AI helps me share complex technical concepts with the global dev community. All architecture, code, and insights come from solving this problem in production. I've tried to present these principles clearly and hope they'll be useful to others working in this field.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #ai #architecture #memory #Recursion&lt;/p&gt;

</description>
      <category>ai</category>
      <category>memory</category>
      <category>recursion</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How I Fixed "pthread_create: Invalid argument" in Node.js (ROCm + Bleeding Edge Linux)</title>
      <dc:creator>Aleksandr Kossarev</dc:creator>
      <pubDate>Mon, 05 Jan 2026 15:21:00 +0000</pubDate>
      <link>https://dev.to/aleksandr_kossarev_e23623/how-i-fixed-pthreadcreate-invalid-argument-in-nodejs-rocm-bleeding-edge-linux-22ak</link>
      <guid>https://dev.to/aleksandr_kossarev_e23623/how-i-fixed-pthreadcreate-invalid-argument-in-nodejs-rocm-bleeding-edge-linux-22ak</guid>
      <description>&lt;p&gt;Every. Single. Time. 🤦‍♂️&lt;/p&gt;

&lt;h2&gt;
  
  
  My Setup (aka "The Perfect Storm")
&lt;/h2&gt;

&lt;p&gt;Before we dive in, here's what I was working with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🖥️ Linux 6.14 (yes, bleeding edge)&lt;/li&gt;
&lt;li&gt;🧠 Intel Core Ultra 9 185H (hybrid P/E cores)&lt;/li&gt;
&lt;li&gt;🎮 AMD RadeonPro W7900 with ROCm 7.0.2&lt;/li&gt;
&lt;li&gt;📦 Node.js 22.21.0&lt;/li&gt;
&lt;li&gt;🔧 glibc 2.39&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sounds like a developer's dream setup, right? Well... &lt;/p&gt;

&lt;h2&gt;
  
  
  The Debugging Journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Phase 1: All the Standard Stuff (That Didn't Work)
&lt;/h3&gt;

&lt;p&gt;I tried everything you'd find on Stack Overflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Clearing npm cache&lt;/li&gt;
&lt;li&gt;❌ Rebuilding Node.js from source&lt;/li&gt;
&lt;li&gt;❌ Adjusting ulimit settings&lt;/li&gt;
&lt;li&gt;❌ Playing with UV_THREADPOOL_SIZE&lt;/li&gt;
&lt;li&gt;❌ Different Node.js versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing. The error kept coming back like a boomerang.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 2: Getting Serious
&lt;/h3&gt;

&lt;p&gt;At this point, I started questioning everything. Is it the hybrid CPU? The kernel version? Thread pool size?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Testing CPU affinity&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;taskset &lt;span class="nt"&gt;-c&lt;/span&gt; 0-11 node &lt;span class="nt"&gt;-v&lt;/span&gt;
node[10234]: pthread_create: Invalid argument  &lt;span class="c"&gt;# Nope&lt;/span&gt;

&lt;span class="c"&gt;# Testing thread pool&lt;/span&gt;
&lt;span class="nv"&gt;$ UV_THREADPOOL_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 node &lt;span class="nt"&gt;-v&lt;/span&gt;
node[10256]: pthread_create: Invalid argument  &lt;span class="c"&gt;# Nope&lt;/span&gt;

&lt;span class="c"&gt;# Testing glibc rseq&lt;/span&gt;
&lt;span class="nv"&gt;$ GLIBC_TUNABLES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;glibc.pthread.rseq&lt;span class="o"&gt;=&lt;/span&gt;0 node &lt;span class="nt"&gt;-v&lt;/span&gt;
node[10312]: pthread_create: Invalid argument  &lt;span class="c"&gt;# Still nope&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Phase 3: The Breakthrough 💡
&lt;/h3&gt;

&lt;p&gt;Finally, I pulled out the big guns: &lt;code&gt;LD_DEBUG&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ LD_DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;libs node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"console.log('test')"&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; pthread
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there it was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/opt/rocm-7.0.2/lib/libamdhip64.so.7: error: symbol lookup error:
  undefined symbol: pthread_setaffinity_np (fatal)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;EUREKA!&lt;/strong&gt; 🎉&lt;/p&gt;

&lt;p&gt;The culprit wasn't Node.js at all. It was ROCm's &lt;code&gt;LD_PRELOAD&lt;/code&gt; polluting the environment!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;LD_PRELOAD
&lt;span class="nv"&gt;LD_PRELOAD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/rocm-7.0.2/lib/libMIOpen.so
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Solution: Wrapper Scripts
&lt;/h2&gt;

&lt;p&gt;Here's the clever part: I needed Node.js to work WITHOUT breaking ROCm for my GPU workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution: Environment isolation through wrapper scripts.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create the wrappers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File: &lt;code&gt;~/.local/bin/node&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Isolate Node.js from ROCm's LD_PRELOAD&lt;/span&gt;
&lt;span class="nb"&gt;unset &lt;/span&gt;LD_PRELOAD
&lt;span class="nb"&gt;exec&lt;/span&gt; /usr/bin/node &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;File: &lt;code&gt;~/.local/bin/npm&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Isolate npm from ROCm's LD_PRELOAD&lt;/span&gt;
&lt;span class="nb"&gt;unset &lt;/span&gt;LD_PRELOAD
&lt;span class="nb"&gt;exec&lt;/span&gt; /usr/bin/npm &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Make them executable
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/.local/bin/node ~/.local/bin/npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Fix your PATH (CRITICAL!)
&lt;/h3&gt;

&lt;p&gt;Edit &lt;code&gt;~/.bashrc&lt;/code&gt; and make sure &lt;code&gt;~/.local/bin&lt;/code&gt; comes FIRST:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# WRONG (wrapper won't be used):&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.local/bin"&lt;/span&gt;

&lt;span class="c"&gt;# RIGHT (wrapper will be used):&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.local/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Verify
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;which node
/home/user/.local/bin/node  &lt;span class="c"&gt;# ✅ Our wrapper!&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;node &lt;span class="nt"&gt;-v&lt;/span&gt;
v22.21.0  &lt;span class="c"&gt;# ✅ NO ERROR! 🎉&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nt"&gt;-v&lt;/span&gt;
10.9.4  &lt;span class="c"&gt;# ✅ Clean!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;p&gt;The wrapper creates a clean environment for Node.js while keeping ROCm functional for other applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Node.js runs without &lt;code&gt;LD_PRELOAD&lt;/code&gt; pollution&lt;/li&gt;
&lt;li&gt;✅ ROCm still works for GPU applications&lt;/li&gt;
&lt;li&gt;✅ Transparent to all programs (terminal, IDE, scripts)&lt;/li&gt;
&lt;li&gt;✅ Easy to maintain and rollback&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Technical Deep-Dive
&lt;/h2&gt;

&lt;p&gt;Want to know &lt;em&gt;why&lt;/em&gt; this happens? It's a "perfect storm":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ROCm's LD_PRELOAD&lt;/strong&gt; forces its libraries to load first&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;These libraries&lt;/strong&gt; have undefined symbols (&lt;code&gt;pthread_setaffinity_np&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js 22&lt;/strong&gt; tries to create threads with these broken symbols in scope&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result:&lt;/strong&gt; &lt;code&gt;pthread_create()&lt;/code&gt; returns EINVAL (errno 22)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The kicker? The program still works because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Main threads are already created&lt;/li&gt;
&lt;li&gt;The error happens in &lt;em&gt;additional&lt;/em&gt; worker threads&lt;/li&gt;
&lt;li&gt;Node.js libuv handles the error gracefully&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it's still annoying as hell to see on every run. 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Bleeding edge = cutting yourself&lt;/strong&gt; - Latest kernel + glibc + Node.js = unexpected interactions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LD_PRELOAD is dangerous&lt;/strong&gt; - It affects &lt;em&gt;every&lt;/em&gt; dynamically linked program&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep tracing saves the day&lt;/strong&gt; - &lt;code&gt;LD_DEBUG&lt;/code&gt; found the issue in one shot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints breed creativity&lt;/strong&gt; - "Don't touch ROCm" → wrapper pattern&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PATH order matters&lt;/strong&gt; - First match wins!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Full Documentation
&lt;/h2&gt;

&lt;p&gt;I've documented the entire diagnostic process, alternative solutions considered, and technical details in a comprehensive PSP (Problem-Solution Pattern):&lt;/p&gt;

&lt;p&gt;📄 &lt;a href="https://gist.github.com/alexk202/efb3562f7d3242a835955f07480db468" rel="noopener noreferrer"&gt;Complete PSP on GitHub Gist&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you're seeing &lt;code&gt;pthread_create: Invalid argument&lt;/code&gt; with Node.js and you have AMD GPU with ROCm installed, check for &lt;code&gt;LD_PRELOAD&lt;/code&gt; pollution. The wrapper script solution is clean, maintainable, and doesn't break your GPU workflows.&lt;/p&gt;

&lt;p&gt;Have you encountered similar issues with environment variable pollution? Let me know in the comments! 👇&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Stats:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⏱️ Time to debug: 2.5 hours&lt;/li&gt;
&lt;li&gt;🧪 Hypotheses tested: 8+&lt;/li&gt;
&lt;li&gt;🎯 Tools used: LD_DEBUG, strace, lscpu, ulimit&lt;/li&gt;
&lt;li&gt;💪 Complexity: 5/5&lt;/li&gt;
&lt;li&gt;🏅 Satisfaction: ∞&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  debugging #linux #nodejs #amd #problemsolving
&lt;/h1&gt;

</description>
      <category>problemsolving</category>
    </item>
  </channel>
</rss>
