Deployment

Troubleshooting

Use these diagnostic steps to resolve common Sheath installation, configuration, parsing, caching, and CI issues.

#Installation Issues

#"Class not found" after installation

Problem: Laravel can't find Sheath classes after installation.

Solution: Confirm that Composer installed the package, then rebuild the autoload files:

composer show fortephp/sheath
composer dump-autoload

If composer show cannot find the package, install it with composer require --dev fortephp/sheath. A deployment that runs composer install --no-dev does not install packages from require-dev.

#Service provider not loaded

Problem: The sheath:lint command isn't available.

Solution: Confirm that the package is installed and that Laravel package discovery has not been disabled for it:

composer require fortephp/sheath --dev

Sheath declares its provider for Laravel package discovery. If your application disables discovery, add the provider to bootstrap/providers.php:

<?php
return [
App\Providers\AppServiceProvider::class,
Forte\Sheath\ServiceProvider::class,
];

#Configuration Issues

#Config file not found

Problem: The run fails with Configuration file not found: sheath.custom.php.

Solution: A --config file that is missing, unreadable, or not a .php or .json file fails the run with exit code 1. Sheath does not fall back to defaults. Ensure the path is relative to the project root or use an absolute path:

# Correct
php artisan sheath:lint --config=sheath.custom.php
# Also correct
php artisan sheath:lint --config=config/sheath.custom.php
# Also correct
php artisan sheath:lint --config=/full/path/to/sheath.custom.php

#Rules not being applied

Problem: Configured rules don't seem to work.

Solution: Use --print-config to debug:

php artisan sheath:lint --print-config

Check that:

  1. Rule IDs are spelled correctly (e.g., a11y-alt-text not alt-text)
  2. Severity values are valid (error, warning, info, off)
  3. Config file syntax is valid PHP or JSON
  4. ruleStatus does not show the rule as skipped or disabled due to package requirements

Unknown rule IDs stop the command before linting. If you see an "Unknown rule" error, compare the ID with the Rules index.

#--only flag not working

Problem: The --only flag doesn't filter to specified rules.

Solution: Ensure rule IDs are comma-separated and spelled correctly:

# Correct
php artisan sheath:lint --only=a11y-alt-text,security-csrf-field
# Also valid
php artisan sheath:lint --only="a11y-alt-text, security-csrf-field"

#Runtime Issues

#Out of memory errors

Problem: PHP runs out of memory on large codebases.

Solution:

# Increase memory limit
php -d memory_limit=512M artisan sheath:lint
# Or lint a narrower path or rule set
php artisan sheath:lint resources/views/admin --only=security-no-raw-echo
# Or use caching to process incrementally
php artisan sheath:lint --cache

Parallel mode targets wall-clock time, not memory use. Because each worker has its own PHP process, --parallel may increase the run's total memory usage.

#Slow performance

Problem: Linting takes too long.

Solutions:

  1. Enable caching to skip unchanged files:

    php artisan sheath:lint --cache
  2. Limit the work during development:

    php artisan sheath:lint resources/views/admin --only=a11y-alt-text,security-no-raw-echo
  3. Use parallel processing after installing the optional runtime packages:

    php artisan sheath:lint --parallel

    Use --parallel-if-available when the same command should run sequentially without a warning on machines that do not have those packages.

  4. Combine caching and parallelism when both help your workload:

    php artisan sheath:lint --parallel --cache
  5. Ignore generated templates inside configured lint paths:

    // config/sheath.php
    'ignore' => [
    'resources/views/vendor/**',
    'resources/views/generated/**',
    ],

#Parser errors on valid Blade

Problem: Sheath reports parser errors on valid Blade syntax.

Solution: Sheath reports the parser diagnostics and skips normal rules for that file. First, check that the template compiles in Laravel. If it does, exclude only that file so Sheath can continue linting the rest of the project. For a single run:

php artisan sheath:lint --ignore-pattern=resources/views/components/problematic.blade.php

To keep the exclusion in place until the parser is fixed, add the narrowest possible path to the existing ignore list:

// config/sheath.php
'ignore' => [
// Ignore one file when possible.
'resources/views/components/problematic.blade.php',
// Or ignore a directory if several related templates are affected.
// 'resources/views/problematic/**',
],

Then create a minimal reproduction:

  1. Copy the failing Blade template into a separate file.
  2. Remove unrelated markup and directives while keeping the same parser error.
  3. Replace project-specific names and data with simple placeholders.
  4. Confirm the reduced example is valid Blade and still produces the error.

Report the reduced example to the Sheath issue tracker. Include the complete parse-error message and your PHP, Laravel, and Sheath versions.

#False Positives

#Suppressing legitimate findings

Problem: A rule is technically correct, but a specific project or template has a legitimate exception.

Solution: Suppress it where it happens, and say why:

{{-- sheath-disable-next-line security-no-raw-echo -- sanitised in the view model --}}
{!! $post->renderedBody !!}

See Inline Suppressions for the comment syntax, and Choosing a Suppression when a broader scope is warranted. See Adoption Recipes for rollout examples.

#Components flagged incorrectly

Problem: Blade components are flagged for issues that don't apply.

Solution: Many rules skip Blade components automatically. If a rule incorrectly flags a component:

  1. Check if the component name follows conventions (x-, livewire:)
  2. If the false positive is limited to a specific directory, exclude that path temporarily with ignore patterns.

#Partial templates flagged

Problem: Partial templates get flagged for missing <html>, <head>, etc.

Solution: Document rules do not run when a template has no relevant document structure, such as an <html> or <head> element. A shared fragment that contains that structure can still be checked. Suppress the specific rule at the fragment when the requirement is satisfied by its parent layout. Ignore the path only when no Sheath rules should run there:

// config/sheath.php
'ignore' => [
'resources/views/partials/generated-head/**',
],

#Baseline Issues

#Baseline not filtering violations

Problem: Known violations still appear despite having a baseline.

Causes:

  1. The file or the code around the finding moved: baselines match on file path, surrounding code, and message. Renaming a file, or editing near a baselined finding, can break the match. Regenerate:

    php artisan sheath:lint --update-baseline
  2. Wrong baseline path: Verify the path:

    php artisan sheath:lint --baseline=sheath-baseline.json

#Baseline file too large

Problem: The baseline file is very large and slow to process.

Solution: This usually means too many violations are baselined. Consider:

  1. Fix low-risk or autofixable violations first
  2. Disable extremely noisy rules in config instead of baselining
  3. Use more specific ignore patterns

#CI/CD Issues

#CI Step Stays Green After Findings

Problem: CI doesn't fail on errors.

Solution: Sheath exits with code 1 for errors, and for warnings above --max-warnings. Check whether the workflow masks that status with a construct such as continue-on-error or || true:

# GitHub Actions
- name: Lint Blade templates
run: php artisan sheath:lint --max-warnings=0

#GitHub annotations not appearing

Problem: Using --format=github but no annotations appear.

Solution: Ensure you're running in a GitHub Actions environment and the step isn't suppressing output:

- name: Lint Blade templates
run: php artisan sheath:lint --format=github

#Different results locally vs CI

Problem: Linting passes locally but fails in CI (or vice versa).

Causes:

  1. Different PHP or dependency versions: Compare PHP versions and install from the same committed composer.lock
  2. Different package availability: First-party plugin rules can run or be skipped according to the packages installed in that environment
  3. Config or baseline differences: Commit the intended config and baseline, then compare php artisan sheath:lint --print-config
  4. Source differences: Confirm generated views and checked-out files match
  5. Cache diagnosis: Run once without --cache; Sheath validates normal persistent entries against source and lint context before reuse

#Fix Issues

#--fix not changing files

Problem: Running with --fix doesn't modify files.

Causes:

  1. No fixable violations: Not all rules have auto-fixes
  2. Dangerous fixes: Some fixes are marked "dangerous" and aren't applied automatically
  3. Dry run mode: Remove --dry-run to apply changes

Use --dry-run first to preview what would change:

php artisan sheath:lint --dry-run

#Fix broke my template

Problem: Auto-fix caused a broken template.

Solution:

  1. Revert with git: git restore path/to/file.blade.php
  2. Report the issue with the original code and the broken result
  3. Consider disabling the rule or excluding the affected path temporarily

#Getting Help

#Debugging

Use these flags to understand what Sheath is doing:

# See resolved configuration
php artisan sheath:lint --print-config
# See performance statistics
php artisan sheath:lint --stats
# Preview fixes without applying
php artisan sheath:lint --dry-run

#Reporting Issues

When reporting bugs, include:

  1. Sheath version: composer show fortephp/sheath
  2. PHP version: php -v
  3. Laravel version: php artisan --version
  4. Minimal reproduction case (Blade code that triggers the issue)
  5. Expected vs actual behavior
  6. Any relevant configuration

File it on the Sheath issue tracker.

#Common Error Messages

Use the reported message to identify the failed input or configuration.

Error Cause Solution
Configuration file not found: <path> The --config path does not exist; the run fails with exit code 1 Check file exists and path is correct
Configuration file is not readable: <path> The --config file exists but cannot be read; the run fails Check file permissions
Unsupported configuration file format: <ext>. Expected a .php or .json file. The --config file is not a .php or .json file; the run fails Point --config at a .php or .json file
Unknown configuration key: <key> A typo such as rule for rules, or a --config file that is not a Sheath config Compare with the full configuration. An empty array is valid and means "use the defaults"
An expected-type message naming a key A non-integer baselineLineTolerance, non-boolean inlineSuppressions, non-array rules, or null for a recognized setting Use the documented type. paths, ignore, neverFix, and preset accept one string or an array of strings
A malformed-rule-entry message A rule entry that is not a severity string, a [severity, options] tuple, or a long-form array Use one of the three entry forms
Invalid severity '<value>' for rule '<id>' Typo in a rule severity Use error, warning, info, or off
Unknown rule: <id> An unrecognized rule ID in the config, --rule, or --only Compare the ID with the Rules index
An invalid-mode message listing skip, disable, ignore Typo in packageRequirementMode Use one of the three modes
parse-error findings, e.g. Unexpected end of file inside a Blade echo. Is a '}}' missing? Invalid Blade syntax or unsupported parser edge case Follow the parser error steps

#See Also