Skip to content

Colored Troubleshooting

RAprogramm edited this page Oct 20, 2025 · 1 revision

Troubleshooting Guide

Solutions to common colored output issues

This guide helps diagnose and resolve issues with colored terminal output in masterror.

Table of Contents

Colors Not Showing

Problem: No colors in terminal output

Symptoms:

Error: Internal server error
Code: INTERNAL
Message: Database connection failed

Plain text appears instead of colored output.

Diagnostic Steps

1. Check TTY Detection

# Test if stderr is a TTY
cargo run --example colored_cli --features colored

# Compare with piped output (should show no colors)
cargo run --example colored_cli --features colored 2>&1 | cat

If both show no colors, proceed to step 2.

2. Check NO_COLOR Environment Variable

echo $NO_COLOR

Solution: If set, unset it:

unset NO_COLOR
cargo run --example colored_cli --features colored

3. Check TERM Environment Variable

echo $TERM

Solution: If TERM=dumb, change it:

export TERM=xterm-256color
cargo run --example colored_cli --features colored

4. Verify Feature Flag

Check Cargo.toml:

[dependencies]
masterror = { version = "0.24", features = ["colored"] }

Solution: If missing, add the colored feature:

cargo add masterror --features colored

5. Check Terminal Emulator

Some old terminals don't support ANSI colors.

Test:

echo -e "\033[31mRed text\033[0m"

If this doesn't show red text, your terminal doesn't support ANSI colors.

Solutions:

  • Linux: Install a modern terminal (Alacritty, GNOME Terminal, Konsole)
  • macOS: Use Terminal.app (built-in) or iTerm2
  • Windows: Use Windows Terminal or ConEmu
  • SSH: Ensure your local terminal supports colors

6. Verify Rust Build

# Clean rebuild with colored feature
cargo clean
cargo build --features colored
cargo run --example colored_cli --features colored

Quick Fix Checklist

  • NO_COLOR is not set: unset NO_COLOR
  • TERM is not dumb: export TERM=xterm-256color
  • Running in interactive terminal (not piped)
  • colored feature enabled in Cargo.toml
  • Terminal emulator supports ANSI colors

ANSI Codes in Logs

Problem: Escape codes appearing in log files

Symptoms:

[2025-10-20T15:04:23.123Z ERROR] Error: ^[[31mInternal server error^[[0m

Raw ANSI codes like ^[[31m appear in logs.

Cause

Colors are being written to log files instead of just terminals.

Solution 1: Disable Colors for File Output

If using tracing-subscriber:

use tracing_subscriber::fmt;

fn init_logging() {
    // Separate layers for stdout and file
    let file_appender = tracing_appender::rolling::daily("/var/log/app", "app.log");
    let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);

    let file_layer = fmt::layer()
        .with_writer(file_writer)
        .with_ansi(false);  // Disable colors for file

    let stdout_layer = fmt::layer()
        .with_writer(std::io::stdout)
        .with_ansi(true);   // Enable colors for terminal

    tracing_subscriber::registry()
        .with(file_layer)
        .with(stdout_layer)
        .init();
}

If using env_logger:

use env_logger::Builder;
use std::io::Write;

fn init_logging() {
    let mut builder = Builder::from_default_env();

    builder.format(|buf, record| {
        // Strip colors when writing to file
        let message = format!("{}", record.args());
        writeln!(buf, "[{}] {}", record.level(), message)
    });

    builder.init();
}

Solution 2: Use NO_COLOR in Production

# In production startup script
export NO_COLOR=1
./my-app

Or in systemd unit file:

[Service]
Environment="NO_COLOR=1"
ExecStart=/usr/bin/my-app

Solution 3: Strip ANSI Codes in Log Processing

If you can't modify the application:

# Strip ANSI codes when viewing logs
cat app.log | sed 's/\x1b\[[0-9;]*m//g'

# Or use a tool like ansistrip
cat app.log | ansistrip

Performance Issues

Problem: Colored output causes slowdown

Symptoms: Application runs slower with colored output enabled.

Diagnosis

Profile your application:

cargo flamegraph --features colored

If TTY detection or color formatting appears in profiles, proceed with optimization.

Solution 1: Reduce Logging Verbosity

// Before: Verbose logging
for item in items {
    trace!("Processing: {}", item);  // Excessive formatting
}

// After: Reduced logging
info!("Processing {} items", items.len());

Solution 2: Lazy Formatting

use tracing::debug;

// Bad: Always formats, even if debug disabled
debug!("User data: {}", expensive_format(&user));

// Good: Only formats if debug enabled
debug!("User data: {}", tracing::field::debug(&user));

Solution 3: Disable Colors in Production

# Cargo.toml for production builds
[profile.release]
strip = true
lto = true

[dependencies]
# Build without colored feature in production
masterror = "0.24"  # No colored feature

Benchmarking

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use masterror::AppError;

fn bench_error_display(c: &mut Criterion) {
    c.bench_function("error_display", |b| {
        let err = AppError::internal("Test error");
        b.iter(|| {
            let _ = format!("{}", black_box(&err));
        });
    });
}

criterion_group!(benches, bench_error_display);
criterion_main!(benches);

Expected performance: < 1μs per error format with colors enabled.

Platform-Specific Problems

Windows 7/8: Colors Not Working

Cause: Old Windows versions don't support ANSI escape codes.

Solutions:

  1. Upgrade to Windows 10+ (recommended)
  2. Use Windows Terminal from Microsoft Store
  3. Disable colors: set NO_COLOR=1

Windows PowerShell: Colors Look Wrong

Cause: PowerShell 5.1 has limited ANSI support.

Solutions:

  1. Use PowerShell 7+ (full ANSI support)
  2. Use Windows Terminal instead of console host
  3. Set $env:NO_COLOR=1 to disable colors

macOS Terminal.app: Dimmed Text Invisible

Cause: Terminal color scheme has low contrast for dimmed text.

Solution: Change Terminal.app color scheme:

  1. Terminal > Preferences > Profiles
  2. Select "Pro" or "Novel" theme (better contrast)
  3. Or customize colors manually

SSH: Colors Not Appearing

Cause: SSH not allocating pseudo-TTY.

Diagnosis:

# On remote host
tty
# Should show: /dev/pts/0 (or similar)
# If shows: not a tty, proceed below

Solution:

# Force TTY allocation
ssh -t user@host cargo run --example colored_cli --features colored

Docker: Colors Not Appearing

Cause: Docker not allocating TTY.

Solution:

# Use -it flags
docker run -it my-app

# Or just -t for TTY without interactive
docker run -t my-app

In docker-compose.yml:

services:
  app:
    image: my-app
    tty: true        # Allocate TTY
    stdin_open: true # Keep stdin open

CI/CD Issues

GitHub Actions: Colors in Logs

Problem: ANSI codes appear in GitHub Actions logs.

Solution: Disable colors in workflow:

name: CI

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: stable

      - name: Run tests
        run: cargo test --features colored
        env:
          NO_COLOR: "1"  # Disable colors in CI

GitLab CI: Colors Not Showing

Problem: Want colors in GitLab CI logs (they support ANSI).

Solution: GitLab CI supports colors by default. Ensure NO_COLOR is not set:

test:
  script:
    - cargo test --features colored
  variables:
    TERM: "xterm-256color"

Jenkins: Raw ANSI Codes

Problem: Jenkins shows ^[[31m instead of colors.

Solution: Install AnsiColor plugin:

pipeline {
    agent any
    options {
        ansiColor('xterm')
    }
    stages {
        stage('Test') {
            steps {
                sh 'cargo test --features colored'
            }
        }
    }
}

Integration Problems

Problem: Colors in HTTP Responses

Symptoms: API clients receive JSON with ANSI codes:

{
  "error": "Error: \u001b[31mInternal server error\u001b[0m"
}

Cause: Error Display implementation used in HTTP response body.

Solution: Use separate error representation for HTTP:

use axum::{response::IntoResponse, Json};
use masterror::AppError;
use tracing::error;

impl IntoResponse for AppError {
    fn into_response(self) -> axum::response::Response {
        // Log with colors
        error!("Request error: {}", self);

        // Return clean JSON (use error fields, not Display)
        let body = Json(serde_json::json!({
            "error": {
                "code": self.code().to_string(),
                "message": self.message().unwrap_or("An error occurred"),
            }
        }));

        (self.kind().status_code(), body).into_response()
    }
}

Problem: Colors in Test Output

Symptoms: Test assertions fail with ANSI codes.

#[test]
fn test_error_message() {
    let err = AppError::internal("test");
    // Fails because output contains ANSI codes
    assert_eq!(err.to_string(), "Error: Internal server error");
}

Solution: Set NO_COLOR in tests:

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_error_message() {
        // Disable colors for predictable test output
        std::env::set_var("NO_COLOR", "1");

        let err = AppError::internal("test");
        let output = err.to_string();

        // Now assertion works
        assert!(output.contains("Internal server error"));
        assert!(!output.contains("\x1b[")); // No ANSI codes
    }
}

Or use contains instead of eq:

#[test]
fn test_error_message() {
    let err = AppError::internal("test");
    let output = err.to_string();

    // Works with or without colors
    assert!(output.contains("Internal server error"));
}

Problem: Colors in tracing JSON Output

Cause: tracing_subscriber JSON formatter receiving colored strings.

Solution: Disable ANSI in JSON layer:

use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter};

fn init_logging() {
    let json_layer = fmt::layer()
        .json()
        .with_ansi(false);  // Never use colors in JSON

    tracing_subscriber::registry()
        .with(EnvFilter::from_default_env())
        .with(json_layer)
        .init();
}

Debugging Tools

Check for ANSI Codes

# Hexdump to see raw bytes
cargo run --example colored_cli --features colored 2>&1 | hexdump -C | head

# Look for escape sequences: 1b 5b (ESC [)

View Raw Output

# Use cat -A to show all control characters
cargo run --example colored_cli --features colored 2>&1 | cat -A

# ANSI codes appear as ^[[31m

Test TTY Detection

fn main() {
    use std::io::IsTerminal;

    if std::io::stderr().is_terminal() {
        eprintln!("stderr IS a TTY");
    } else {
        eprintln!("stderr is NOT a TTY");
    }

    eprintln!("NO_COLOR: {:?}", std::env::var("NO_COLOR"));
    eprintln!("TERM: {:?}", std::env::var("TERM"));
}

Inspect owo-colors Behavior

use owo_colors::{OwoColorize, Stream};

fn main() {
    let text = "Test";

    let colored = text.if_supports_color(Stream::Stderr, |t| t.red());

    eprintln!("Output: {}", colored);
    eprintln!("Contains ANSI: {}", colored.to_string().contains("\x1b["));
}

Getting Help

If none of these solutions work:

  1. Check masterror version: Ensure you have the latest version

    cargo update masterror
  2. Verify owo-colors: Check dependency tree

    cargo tree | grep owo-colors
  3. Open an issue: https://github.com/RAprogramm/masterror/issues

    • Include your OS and terminal
    • Provide echo $TERM output
    • Show cargo --version and rustc --version
    • Include minimal reproduction code

Related Pages:


Previous: Integration Guide | Next: Migration Guide

Clone this wiki locally