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:
- Rule IDs are spelled correctly (e.g.,
a11y-alt-textnotalt-text) - Severity values are valid (
error,warning,info,off) - Config file syntax is valid PHP or JSON
ruleStatusdoes 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:
-
Enable caching to skip unchanged files:
php artisan sheath:lint --cache -
Limit the work during development:
php artisan sheath:lint resources/views/admin --only=a11y-alt-text,security-no-raw-echo -
Use parallel processing after installing the optional runtime packages:
php artisan sheath:lint --parallelUse
--parallel-if-availablewhen the same command should run sequentially without a warning on machines that do not have those packages. -
Combine caching and parallelism when both help your workload:
php artisan sheath:lint --parallel --cache -
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:
- Copy the failing Blade template into a separate file.
- Remove unrelated markup and directives while keeping the same parser error.
- Replace project-specific names and data with simple placeholders.
- 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:
- Check if the component name follows conventions (
x-,livewire:) - 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:
-
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 -
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:
- Fix low-risk or autofixable violations first
- Disable extremely noisy rules in config instead of baselining
- 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:
- Different PHP or dependency versions: Compare PHP versions and install
from the same committed
composer.lock - Different package availability: First-party plugin rules can run or be skipped according to the packages installed in that environment
- Config or baseline differences: Commit the intended config and baseline,
then compare
php artisan sheath:lint --print-config - Source differences: Confirm generated views and checked-out files match
- 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:
- No fixable violations: Not all rules have auto-fixes
- Dangerous fixes: Some fixes are marked "dangerous" and aren't applied automatically
- Dry run mode: Remove
--dry-runto 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:
- Revert with git:
git restore path/to/file.blade.php - Report the issue with the original code and the broken result
- 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:
- Sheath version:
composer show fortephp/sheath - PHP version:
php -v - Laravel version:
php artisan --version - Minimal reproduction case (Blade code that triggers the issue)
- Expected vs actual behavior
- 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
- Configuration - Config file reference
- CLI Usage - All command options
- Baseline - Working with error baselines
- Custom Rules - Writing custom rules