The Error That Started It All
$ powerprofilesctl get
Traceback (most recent call last):
File "/usr/bin/powerprofilesctl", line 8, in <module>
from gi.repository import Gio, GLib
ModuleNotFoundError: No module named 'gi'
Fresh off optimizing my Sway configuration for laptop power management, I hit this wall. The power-profiles-daemon was installed, the service was running, but the CLI tool was completely broken.
The mise Factor
Here’s where it gets interesting. I use mise to manage my development environments:
$ mise current
node 24.6.0
python 3.13.7 ← This is the problem child
ruby 3.4.5
# ... other tools
$ which python3
/home/seuros/.local/share/mise/installs/python/3.13.7/bin/python3
Mise creates isolated environments for each tool. Great for development, but it can cause unexpected conflicts with system integration.
The Diagnosis Dance
Let’s trace what’s happening:
# Check if gi module works with mise Python
$ ~/.local/share/mise/installs/python/3.13.7/bin/python3 -c "import gi; print('gi module found')"
Traceback (most recent call last):
File "<string>", line 1, in <module>
import gi; print('gi module found')
^^^^^^^^^
ModuleNotFoundError: No module named 'gi'
# Check with system Python
$ /usr/bin/python3 -c "import gi; print('gi module found')"
gi module found
Bingo! The gobject-introspection library (python-gobject
package) is installed for the system Python, not the mise-managed one.
The Shebang Showdown
Here’s the culprit:
$ head -1 /usr/bin/powerprofilesctl
#!/usr/bin/env python3
That innocent-looking shebang resolves to whatever python3
is in your PATH. With mise active, that’s:
#!/usr/bin/env python3
→/home/seuros/.local/share/mise/installs/python/3.13.7/bin/python3
- No
gi
module → crash
But if we force it to use the system Python:
#!/usr/bin/python3
→/usr/bin/python3
- System packages available → success
The One-Line Fix
# Backup first (always)
$ sudo cp /usr/bin/powerprofilesctl /usr/bin/powerprofilesctl.orig
# Fix the shebang
$ sudo sed -i '1s|#!/usr/bin/env python3|#!/usr/bin/python3|' /usr/bin/powerprofilesctl
# Test the fix
$ powerprofilesctl get
balanced
$ powerprofilesctl list
performance:
CpuDriver: intel_pstate
Degraded: no
* balanced:
CpuDriver: intel_pstate
PlatformDriver: placeholder
power-saver:
CpuDriver: intel_pstate
PlatformDriver: placeholder
Perfect! Now my Sway power management works flawlessly:
- Auto-switches to power-saver on battery
- Reduces SwayFX effects for better performance
- Enables full visual effects when plugged in
The Broader Lesson
This is a classic case of modern tooling vs. system integration. Tools like mise, pyenv, nvm, and rbenv create isolated environments that can break system scripts expecting global interpreters.
The fix patterns:
- For scripts you control: Use virtual environments properly
- For system scripts: Force absolute paths to system interpreters
- For development: Be aware of which environment you’re in
Prevention Tips
# Check what your environment resolves to
$ which python3
$ /usr/bin/env python3 --version vs /usr/bin/python3 --version
# For system packages that include Python scripts,
# consider if they need system Python specifically
$ pacman -Ql power-profiles-daemon | grep bin/
Sometimes the simplest bugs have the most educational value. A single character change (env
removal) solved hours of head-scratching and taught me about the subtle ways development tools can interfere with system integration.
Aftermath
My Sway setup now dynamically adjusts performance based on power state, all thanks to fixing this Python environment conflict. The lesson? When mise meets system packages, shebangs matter.
# This now works perfectly
$ powerprofilesctl set power-saver && echo "Battery mode activated"
$ powerprofilesctl set performance && echo "Plugged in, full power"
The fix is deployed, the laptop is optimized, and I learned something new about Python environment isolation. Not bad for a debugging session.