Terminal-এর দিকে Twenty Minutes তাকিয়ে ছিলাম। Error Message দশ লাইন Long, কোনো File Reference করছিল Nix Store-এ Hash যেটা মনে রাখবো না, আর কিছু বলছিল "infinite recursion" বা "attribute missing" বা... কিছু একটা। আর মনে নেই। শুধু Feeling মনে আছে: Nix error message পড়ার উপায় না জানলে এই ইকোসিস্টেমে টিকে থাকা অসম্ভব। Nix একটা Language Speak করছিল আমি বুঝি না, আর আমি Fail করছিলাম।

Nix error message পড়ার উপায়: Anatomy অফ অ্যান এরর

বেশিরভাগ Nix Error-এ চারটা Distinct Layer থাকে। গত সপ্তাহে Hit করা একটা Real Error দেখি:

error: infinite recursion encountered
       at /nix/var/nix/profiles/per-user/root/channels/nixpkgs/lib/attrsets.nix:123:5
          122|   recursiveUpdate = x: y:
          123|     mapAttrs (name: val:
             |     ^
          124|       if builtins.isAttrs val && builtins.isAttrs x.${name} or null
       … while evaluating a nested attribute set
       … while calling the 'map' builtin
       … in the expression at /home/user/flake.nix:42:8

ভয়াবহ দেখায়, তাই না? কিন্তু এটা চারটা Specific জিনিস বলছে:

Error type (প্রথম লাইন): infinite recursion encountered। এটা কী ভুল হলো — নecessarily কোথায় নয়, কিন্তু Problem-এর Class।

Location (দ্বিতীয় লাইন): File আর Line Number যেখানে Nix Crash করেছে। সাধারণত Nixpkgs-এর Deep। Rarely কিছু Fix করতে হয় এখানে।

Trace ("… while" লাইন গুলো): Evaluation Stack, Function Call Chain দেখায়। Bottom থেকে Top পড়লে Code-এর Path থেকে Crash Site পর্যন্ত দেখায়।

Your code (শেষ "… in" লাইন): শেষ Trace Entry Almost Always Closest তোমার Introduce করা Problem-এ। এখান থেকে Debug শুরু করো।

আমার শেখা Rule: Top-এর Error Location হলো Nix Crash করেছে। তোমার Bug Almost Always Trace-এর Last Line-এ — বা তার ঠিক উপরে। Bottom-up পড়ো।

পাঁচটা Error Class যেগুলো Actually দেখবে

Nix Error গুলো কয়েকটা Recurring Type-এ Group হয়। Sight-এ Recognize করলে Diagnostic Work-এর বেশিরভাগ Save হয়।

1. Infinite Recursion Encountered

এটা মানে Nix এমন Attribute Evaluate করতে চেয়েছে যেটা নিজের উপর Depend করে। Common Causes: Overlay-এ self বা super Incorrect Use করা, বা callPackage যেখানে Attribute Defined হচ্ছে সেই Derivation-এর দিকে Refer Back করে।

# Classic trap: 'pkgs' fully construct হওয়ার আগে Refer করা
let
  pkgs = import <nixpkgs> { overlays = [ overlay ]; };
  overlay = final: prev: {
    myPkg = pkgs.stdenv.mkDerivation { ... }; # ← হওয়া উচিত 'final.stdenv'
  };
in pkgs

Debug strategy: nix build বা nix eval-এ --show-trace Add করো। Trace ঠিক কোন Attribute Cycle Trigger করেছে Point করবে।

2. Value Is Not a Function / Not an Attribute Set

Nix-এর Type System Lazy — Errors শুধু Evaluation-এর সময় Surface করে। মানে তুমি Wrong Shape Pass করেছো। Usually Missing Argument, Attribute Name-এ Typo, বা Function Apply করা ভুলে।

# Often caused by:
let
  f = { foo }: foo + 1;
in
f 42  # int Pass করা Function-এ Expecting Attrset

Error বলে "value is not an attribute set" আর Nixpkgs-এ Point করে, সাধারণত মানে Derivation Pass করেছো যেখানে Options Set Expect করছিল, বা উল্টো — যেমন pkgs.python3.withPackages Call করা এবং Lambda ভুলে।

3. Attribute Not Found

Nixpkgs Newcomers-এর সবচেয়ে Common Error। Set-এ এমন Attribute Access করার চেষ্টা করছো যেটা Exist করে না। Spelling Check করো, Package Right Channel-এ আছে কিনা Check করো, আর Package Set (যেমন pkgs.python3Packages) আর Package (pkgs.python3) Confuse করছো কিনা দেখো।

error: attribute 'pythonPackages' missing

# Attribute set 'pkgs'-এর এই Path আছে, শুধু নাম আলাদা:
# pkgs.python3Packages.requests   ← correct
# pkgs.pythonPackages.requests    ← exist করে না

4. Builder Failed with Exit Code N

এটা Build-time Error, Evaluation Error নয়। Nix Successfully তোমার Derivation Evaluate করেছে, কিন্তু Build Script Fail করেছে। Error Message Itself Almost Never Useful — Real Information Build Log-এ।

error: builder for '/nix/store/...-my-package-1.0.drv' failed with exit code 1
       For full logs, run 'nix log /nix/store/...-my-package-1.0.drv'.

Critical: Always nix log /nix/store/... Immediately Run করো। Exit Code Alone কিছু বলে না। Log Everything বলে — Missing Headers, Failed Tests, Network Errors, Wrong Phase Outputs।

5. Hash Mismatch

fetchurl, fetchgit, বা Similar Fetcher Content পেয়েছে Declared Hash Match করে না। Either Derivation-এ Stale Hash, বা Upstream Source In-place Change করেছে (যেটা Hope করার চেয়ে বেশি হয়)।

error: hash mismatch in fixed-output derivation '/nix/store/...':
         specified: sha256-AAAA...
         got:       sha256-BBBB...

Hash Update করে Fix করো। "Got" Value টা Correct — Derivation-এ Copy করো। fetchgit-এর জন্য, Source Move করলে rev Update করো।

Trace Strategically পড়া

"… while evaluating" লাইন গুলো Reverse Evaluation Order-এ Stack Trace Form করে। Top দেখার Instinct resist করো। Top হলো Crash Site, Library-এর Deep। Bottom হলো Code-এর Entry Point।

"Trace টা হলো Backwards Point করা Telescope। Furthest Point হলো যেখানে ভাঙেছে। তোমার Eye Lens-এ Start করা উচিত।"

এখানে একটা বড় সমস্যা আছে। Nix এর এরর মেসেজ মাঝে মাঝে এমন এমন জায়গার কথা বলে যেটার সাথে আমার কোডের কোনো সম্পর্কই নেই। বিশেষ করে যখন lib ফাংশনগুলো ব্যবহার করি, এররটা থ্রো হয় nixpkgs এর ভেতর থেকে। ওই হিপ অফ ট্র্যাশ স্ট্যাক ট্রেস দেখে অনেক সময় মাথা খারাপ হয়ে যায়। মনে হয় যেন আমি অন্ধকার ঘরে হাতড়াচ্ছি।

আমার Process:

  1. শেষ "… in the expression" লাইন খুঁজো। এটা সাধারণত তোমার Code Point করে। File Open করে Line-এ যাও।

  2. One frame up পড়ো। পরের "… while" লাইন বলে Nix তোমার Value দিয়ে কী করছিল — Function Call, List Iterate, Attribute Set Construct।

  3. Operation Match করো Error Type-এর সাথে। বলে "while evaluating a nested attribute set" আর Error "infinite recursion" হলে, Entry Point-এ Circular Attribute Reference খোঁজো।

  4. Nixpkgs-এর Entirely Inside Frames Ignore করো যদি Overlay বা Patch না লিখছো। সেই Frames হলো Symptoms, Causes নয়।

  5. যখন Unsure, builtins.trace Probes Add করো। Suspect Expression-এর কাছে builtins.trace "reached here: ${builtins.typeOf x}" x Drop করে Confirm করো কী Evaluate হচ্ছে আর কি Shape-এ।

Practical Debugging Commands

Theory জানা এক জিনিস। এগুলো হলো Commands যেগুলো Actually Reach for করবে:

# Eval Errors-এর জন্য Always --show-trace Add করো
nix build .#myPackage --show-trace

# Single Attribute Evaluate করো Build না করে
nix eval .#packages.x86_64-linux.myPackage.name

# Nix repl-এ Enter করে Directly Value পোকা করো
nix repl
:lf .                    # current flake Load করো
packages.x86_64-linux.myPackage.buildInputs

# Builder Failure-এর পর Full Build Log Read করো
nix log /nix/store/HASH-myPackage-1.0.drv

# Derivation কী Build করবে Inspect করো Build না করে
nix show-derivation .#myPackage

Leveling Up: Better REPL

Default nix repl Barebones। Months :lf . Type করে আর Manual Navigate করার পর, Custom repl.nix Build করেছিলাম যেটা Preload করে সব Host, Configs, আর Helper Functions।

{
  # Repl Start করার সময় Host Name Pass করো
  host ? "xenomorph",
  ...
}:
let
  flake = builtins.getFlake (toString ./.);
  inherit (flake.inputs.nixpkgs) lib;
in
{
  inherit lib;
  inherit (flake) inputs;

  # Current Host-এর Quick Access
  c = flake.nixosConfigurations.${host}.config;
  config = c;
  co = c.custom;
  pkgs = flake.nixosConfigurations.${host}.pkgs;

  # Debugging-এর জন্য Helper Functions
  keys = lib.attrNames;                    # Set-এর সব Attributes List করো
  deps = pkg: map (p: p.name or "unknown") (pkg.buildInputs ++ pkg.nativeBuildInputs or []);

  # কোন Option কোথায় Defined খুঁজো (nixos internals Filter করে)
  where = path: let
    opt = lib.attrByPath (lib.splitString "." path) null
          flake.nixosConfigurations.${host}.options;
    decls = if opt != null && opt ? files then opt.files else [];
    isMine = f: !(lib.hasInfix "nixos/modules/" (toString f));
    in lib.filter isMine decls;

  # Repl Exit না করে Reload
  reload = import ./repl.nix { inherit host; };
}
// flake.nixosConfigurations  # সব Host Configs Merge করো

কেন এটা Better:

  • keys pkgs: :p pkgs Type করে 50,000 Attributes Scroll করার পরিবর্তে Clean List পাও
  • where "services.nginx.virtualHosts": Exact File খুঁজে পাও যেটা Option Define করে, Nixpkgs Internals Ignore করে
  • deps pkgs.hello: Nixpkgs Source Dig না করে কোনো Package-এর Build Inputs দেখো
  • c / config / co: Current Host-এর Config আর Custom Options-এর Short Aliases
  • reload: Repl Exit না করে repl.nix Re-import করো (Repl Itself Edit করার সময় Great)

Helper Script দিয়ে Use করা:

#!/usr/bin/env bash
if [[ -f repl.nix ]]; then
  nix repl --arg host '"xenomorph"' --file ./repl.nix "$@"
else
  # repl.nix না থাকলে Regular repl-এ Fallback
  nix repl .
fi

এখন Error Hit করলে Repl-এ Jump করে Immediately Values Inspect করতে পারি:

nix-repl> c.services.nginx.enable
true

nix-repl> where "services.nginx.virtualHosts"
[ /home/k1ng/nix/dotfiles.nix/modules/web/nginx.nix ]

nix-repl> keys co.persist.home
directories files

nix-repl> deps pkgs.neovim
[ "libuv" "msgpack" "tree-sitter" ... ]

Inspiration টা Brian McGee-এর Post থেকে এসেছিল Nix-এর Slow Feedback Loop নিয়ে। REPL Real Debugging Tool হয়ে যায়, শুধু Calculator নয়।

Quick Reference

Errorমানে কীপ্রথমে কী Try করবে
infinite recursionCircular Attribute DependencyOverlays আর self/super Usage Check করো
not a functionWrong type passednix repl-এ Arg Shapes Check করো
attribute missingTypo বা Wrong Channelnix search nixpkgs <name> Run করো
builder failedBuild-time ErrorFull Log nix log দিয়ে Always Read করো
hash mismatchHash Update করো"Got" Value Derivation-এ Copy করো
Reading tracesBottom-up পড়োEntry Point শেষে, Top-এ নয়

Resources

Meta Description: Nix error message দেখে ঘাবড়ে যাওয়ার কিছু নেই। এই গাইডে শিখুন কিভাবে Nix-এর ক্রিপটিক এররগুলো ডিকোড করতে হয় এবং ডিবাগিং প্রসেস সহজ করতে হয়।

Asaduzzaman Pavel

About the Author

Asaduzzaman Pavel is a Software Engineer who actually enjoys the friction of a well-architected system. He has over 15 years of experience building high-performance backends and infrastructure that can actually handle the real-world chaos of scale.

Currently looking for new opportunities to build something amazing.