Avoid YAML Pitfalls: Use File Descriptors and Quote Your Variables
In the process of upgrading our internal tooling, we uncovered two important best practices that will help you avoid subtle and frustrating issues when working with Helm, Docker, CI/CD, or any system that deals with environment variables and YAML-based configurations.
Let’s walk through what happened and how to fix it: the right way.
Use File Descriptors Instead of Symbols
We encountered this issue when we upgraded helmfile to a newer version. This brought in stricter YAML parsing behavior, which surfaced a parsing error when trying to apply one of our Helm charts.
Here’s the stack trace we encountered:
cutting template expressions in release "app-dev":
failed cloning release "app-dev": [643:26] block sequence entries are not allowed in this context 640 | schedule: 0 23 * * 6
641 | - env:
642 | ENVIRONMENT: dev
> 643 | GUNICORN_ACCESS_LOG: -
^
644 | GUNICORN_ERROR_LOG: -
645 | GUNICORN_PORT: '8080'
646 | GUNICORN_WORKER_COUNT: '2'
The issue? YAML misinterpreted the - symbol as a block sequence indicator rather than a string value.
The Fix
Replace the ambiguous - with a clear, POSIX-compliant file descriptor path:
- name: GUNICORN_ACCESS_LOG
value: "/proc/self/fd/1"
- name: GUNICORN_ERROR_LOG
value: "/proc/self/fd/2"This is functionally equivalent (still stdout/stderr), but it avoids YAML parsing issues and is much clearer to anyone reading your configuration.
Why This Matters
- Prevents unexpected YAML parsing errors
- Adheres to POSIX standards (universally supported)
- Self-documenting — avoids confusion about what
-means - Works across tooling: Helm, Docker, apps, CI/CD, etc.
Where You Should Apply This
Update all places where you define log output streams:
- Helm charts
- Dockerfiles
- Application configs
- Shell scripts or entrypoints
- CI/CD configuration files
Unless you’re writing logs to a specific file, always use
/proc/self/fd/1and/proc/self/fd/2for stdout and stderr.
Always Quote Your Variables
Another common issue we’ve seen (and corrected recently) is unquoted variables in YAML or shell configs, especially those containing special characters like dots, dashes, asterisks, or colons.
Don’t do this:
APP_SERVER_ADDRESS: app.dev.internal.company.com:7283Do this instead:
APP_SERVER_ADDRESS: "app.dev.internal.company.com:7283"Why You Should Quote
- Prevents shell expansion issues (
*becomes literal instead of wildcard) - Avoids security vulnerabilities from unescaped values
- Ensures consistent string interpretation across tools
- Keeps YAML parsing happy , especially with values that look like numbers, booleans, or special characters
Where to Apply This
Quote your variables anywhere they’re defined:
.envfilesvalues.yamlin Helmdocker-compose.yaml- Shell profiles (
.bashrc,.zshrc) - GitHub Actions or CI/CD configs
Final Thoughts
These issues surfaced because of stricter parsing in updated tooling, but the underlying best practices have always applied. We should be handling environment values and output streams explicitly and consistently, not just where errors occur.
By quoting your variables and using proper file descriptors, you:
- Future-proof your configs
- Avoid subtle bugs
- Improve readability for others (and future you)
Hope this helps anyone who are facing similar issues as us.. cheers
