Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/core/whats-new/dotnet-10/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ File-based apps also include enhanced features:
- **Runtime path access**: App file and directory paths are available at runtime via `System.AppContext.GetData`.
- **Enhanced shebang support**: Direct shell execution with improved shebang handling, including support for extensionless files.

To help you identify the entry point in multi-file file-based apps, analyzer [CA2266](../../../fundamentals/code-analysis/quality-rules/ca2266.md) warns when the entry-point file doesn't start with a shebang line.

Comment thread
jjonescz marked this conversation as resolved.
Outdated
#### Project referencing example

```csharp
Expand Down
1 change: 1 addition & 0 deletions docs/fundamentals/code-analysis/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ The following rules are enabled, by default, as errors or warnings in .NET 10. A
| [CA2261](quality-rules/ca2261.md) | Usage | Warning | .NET 8 | Do not use `ConfigureAwaitOptions.SuppressThrowing` with `Task<TResult>` |
| [CA2264](quality-rules/ca2264.md) | Usage | Warning | .NET 9 | Do not pass a non-nullable value to `ArgumentNullException.ThrowIfNull` |
| [CA2265](quality-rules/ca2265.md) | Usage | Warning | .NET 9 | Do not compare `Span<T>` to `null` or `default` |
| [CA2266](quality-rules/ca2266.md) | Usage | Warning | .NET 10 | File-based program entry point should start with `#!` |

# [.NET 9](#tab/net-9)

Expand Down
97 changes: 97 additions & 0 deletions docs/fundamentals/code-analysis/quality-rules/ca2266.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: "CA2266: File-based program entry point should start with '#!'"
description: "Learn about code analysis rule CA2266 - File-based program entry point should start with '#!'"
ms.date: 05/21/2026
f1_keywords:
- CA2266
helpviewer_keywords:
- CA2266
dev_langs:
- CSharp
Comment thread
jjonescz marked this conversation as resolved.
ai-usage: ai-assisted
---

# CA2266: File-based program entry point should start with `#!`

| Property | Value |
|-------------------------------------|----------------------------------------------------|
| **Rule ID** | CA2266 |
| **Title** | File-based program entry point should start with `#!` |
| **Category** | [Usage](usage-warnings.md) |
| **Fix is breaking or non-breaking** | Non-breaking |
| **Enabled by default in .NET 10** | As warning |
| **Applicable languages** | C# |

## Cause

Your entry point file in a multi-file file-based program doesn't start with a shebang (`#!`) line.

## Rule description

For correct tool identification and direct shell execution support, start the entry point file with a shebang (`#!`) line to clearly distinguish it from files brought in with `#:include`.

## How to fix violations

Add a shebang line to the beginning of the entry point file, for example, `#!/usr/bin/env dotnet`.

## Example

The following code snippet shows a violation of CA2266.

In `app.cs`:

```csharp
#:include "helpers.cs"

Console.WriteLine(GetMessage());
```

In `helpers.cs`:

```csharp
string GetMessage() => "Hello";
```

The following code snippet fixes the violation.

In `app.cs`:

```csharp
#!/usr/bin/env dotnet
#:include "helpers.cs"

Console.WriteLine(GetMessage());
```

In `helpers.cs`:

```csharp
string GetMessage() => "Hello";
```

## When to suppress warnings

If you intentionally omit the shebang line and have confirmed that your tooling can still identify the entry point correctly, it is safe to suppress this warning.

## Suppress a warning

If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.

```csharp
#pragma warning disable CA2266
// The code that's violating the rule is on this line.
#pragma warning restore CA2266
Comment thread
jjonescz marked this conversation as resolved.
Outdated
```

To disable the rule for a file, folder, or project, set its severity to `none` in the [configuration file](../configuration-files.md).

```ini
[*.cs]
dotnet_diagnostic.CA2266.severity = none
```

For more information, see [How to suppress code analysis warnings](../suppress-warnings.md).

## See also

[Build file-based apps](../../../csharp/fundamentals/tutorials/file-based-programs.md)
Comment thread
jjonescz marked this conversation as resolved.
Outdated
1 change: 1 addition & 0 deletions docs/fundamentals/code-analysis/quality-rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ The following table lists code quality analysis rules.
> | [CA2263: Prefer generic overload when type is known](ca2263.md) | Using a generic overload is preferable to passing a <xref:System.Type?displayProperty=fullName> argument when the type is known, because they promote cleaner and more type-safe code with improved compile-time checks. |
> | [CA2264: Do not pass a non-nullable value to `ArgumentNullException.ThrowIfNull`](ca2264.md) | `ArgumentNullException.ThrowIfNull` throws when the passed argument is `null`. Certain constructs like non-nullable structs, and `nameof()` and `new` expressions are known to never be null, so `ArgumentNullException.ThrowIfNull` will never throw. |
> | [CA2265: Do not compare `Span<T>` to `null` or `default`](ca2265.md) | Comparing a span to `null` or `default` might not do what you intended. `default` and the `null` literal are implicitly converted to `Span<T>.Empty`. |
> | [CA2266: File-based program entry point should start with `#!`](ca2266.md) | When a file-based program consists of multiple files, the entry point file should start with a shebang (`#!`) line to clearly distinguish it from other included files. |
> | [CA2300: Do not use insecure deserializer BinaryFormatter](ca2300.md) | Insecure deserializers are vulnerable when deserializing untrusted data. An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. |
> | [CA2301: Do not call BinaryFormatter.Deserialize without first setting BinaryFormatter.Binder](ca2301.md) | Insecure deserializers are vulnerable when deserializing untrusted data. An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. |
> | [CA2302: Ensure BinaryFormatter.Binder is set before calling BinaryFormatter.Deserialize](ca2302.md) | Insecure deserializers are vulnerable when deserializing untrusted data. An attacker could modify the serialized data to include unexpected types to inject objects with malicious side effects. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Usage rules support proper usage of .NET.
| [CA2260: Implement generic math interfaces correctly](ca2260.md) | Generic math interfaces require the derived type itself to be used for the self-recurring type parameter. |
| [CA2261: Do not use `ConfigureAwaitOptions.SuppressThrowing` with `Task<TResult>`](ca2261.md) | The `ConfigureAwaitOptions.SuppressThrowing` option isn't supported by the generic `Task<TResult>`, since that might lead to returning an invalid `TResult`. |
| [CA2262: Set `MaxResponseHeadersLength` properly](ca2262.md) | Make sure the `MaxResponseHeadersLength` value is provided correctly. This value is measured in kilobytes. |
| [CA2263: Prefer generic overload when type is known](ca2263.md) | Using a generic overload is preferable to passing a <xref:System.Type?displayProperty=fullName> argument when the type is known, because they promote cleaner and more type-safe code with improved compile-time checks. |
| [CA2264: Do not pass a non-nullable value to 'ArgumentNullException.ThrowIfNull'](ca2264.md) | 'ArgumentNullException.ThrowIfNull' throws when the passed argument is 'null'. Certain constructs like non-nullable structs, and 'nameof()' and 'new' expressions are known to never be null, so 'ArgumentNullException.ThrowIfNull' will never throw. |
| [CA2265: Do not compare `Span<T>` to `null` or `default`](ca2265.md) | Comparing a span to `null` or `default` might not do what you intended. `default` and the `null` literal are implicitly converted to `Span<T>.Empty`. |
| [CA2263: Prefer generic overload when type is known](ca2263.md) | Using a generic overload is preferable to passing a <xref:System.Type?displayProperty=fullName> argument when the type is known, because they promote cleaner and more type-safe code with improved compile-time checks. |
| [CA2266: File-based program entry point should start with `#!`](ca2266.md) | When a file-based program consists of multiple files, the entry point file should start with a shebang (`#!`) line to clearly distinguish it from other included files. |
2 changes: 2 additions & 0 deletions docs/navigate/tools-diagnostics/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3674,6 +3674,8 @@ items:
href: ../../fundamentals/code-analysis/quality-rules/ca2264.md
- name: CA2265
href: ../../fundamentals/code-analysis/quality-rules/ca2265.md
- name: CA2266
href: ../../fundamentals/code-analysis/quality-rules/ca2266.md
- name: Code style rules
items:
- name: Overview
Expand Down
Loading