[Bug]: Files starting with PACKAGE_NAME := ... misclassified as binary and skipped

Author: zxiexCreated Mar 22, 2026Updated Jul 2, 2026
Labelsbug

What happened?

Summary

Cookiecutter incorrectly classifies certain plain text template files as binary when they start with:

PACKAGE_NAME := {{ cookiecutter.project_slug }}

As a result, the file is copied without Jinja rendering, leaving template variables unresolved.


Expected Behavior

The file should be treated as text and rendered:

PACKAGE_NAME := example-package

Actual Behavior

The file is treated as binary and copied as-is:

PACKAGE_NAME := {{ cookiecutter.project_slug }}

No warning or error is emitted.


Root Cause

Cookiecutter uses the binaryornot library to determine whether a file is binary.

The file starts with:

PACKAGE_NAME := ...

The first bytes are:

PACK

binaryornot includes b"PACK" in its binary signature list, so:

chunk.startswith(b"PACK") → True

This results in a false positive binary classification, causing Cookiecutter to skip rendering entirely.


Debug Evidence

python
from binaryornot.check import is_binary
print(is_binary("foo_file"))  # True
python
from binaryornot.helpers import _BINARY_SIGNATURES
chunk = b'PACKAGE_NAME := {{ cookiecutter.project_slug }}\n'
for sig in _BINARY_SIGNATURES:
    if chunk.startswith(sig):
        print(sig)

Output:

b'PACK'

Workarounds

Any of the following avoids the issue:

  • Add a blank line
PACKAGE_NAME := {{ cookiecutter.project_slug }}
  • Add a comment
# Generated by cookiecutter
PACKAGE_NAME := {{ cookiecutter.project_slug }}
  • Rename variable
PROJCT_NAME := {{ cookiecutter.project_slug }}

Proposed Enhancement

Since binary detection is heuristic and can produce false positives, it would be useful to provide a way to override it.

Proposal

Add a configuration option similar to _copy_without_render, for example:

json
{
  "_force_render": [
    "Makefile",
    "foo_file",
    "*.mk"
  ]
}

Suggested Behavior

  1. If path matches _copy_without_render → copy without rendering
  2. If path matches _force_render → always render as text
  3. Otherwise → use binary detection

Benefits

  • Avoids fragile reliance on heuristics
  • Gives template authors explicit control
  • Solves real-world edge cases like this one
  • Maintains backward compatibility

Impact

  • Silent rendering failures
  • Hard to debug without --verbose
  • Affects common files (e.g., Makefile, config files)
  • Any file starting with PACK... may be impacted

Conclusion

This is a false positive in binary detection leading to skipped rendering. A configurable override would make Cookiecutter more robust and predictable.

Steps to reproduce

  1. Create a minimal template:
json
cookiecutter.json
{
  "project_slug": "example-package"
}
{{cookiecutter.project_slug}}/foo_file
PACKAGE_NAME := {{ cookiecutter.project_slug }}
  1. Run:
cookiecutter --no-input /path/to/template
  1. Inspect output:
cat example-package/foo_file

Template

cookiecutter.json

{
  "project_slug": "example-package"
}

Output / traceback

bash

Cookiecutter version

2.7.1

Python version

3.12

Operating system

Linux

How did you install Cookiecutter?

uv

Additional context

No response

Source: cookiecutter/cookiecutter