The annotation for nullable reference types should only be used in code within a '#nullable' context

Solution 1:

For anyone ending up here. You can put #nullable enable on top of the file for a file-by-file approach as suggested by @Marc in the comments.

You can also use combinations of #nullable enable/disable to annotate just parts of the file

class Program
{
    static void Main(string[] args)
    {
#nullable enable
        string? message = "Hello World";
#nullable disable
        string message2 = null;

        Console.WriteLine(message);
        Console.WriteLine(message2);
    }
}

Here's a link to the docs. https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references#nullable-contexts

Nullable contexts enable fine-grained control for how the compiler interprets reference type variables. The nullable annotation context of any given source line is either enabled or disabled. You can think of the pre-C# 8.0 compiler as compiling all your code in a disabled nullable context: any reference type may be null. The nullable warnings context may also be enabled or disabled. The nullable warnings context specifies the warnings generated by the compiler using its flow analysis.

The nullable annotation context and nullable warning context can be set for a project using the Nullable element in your .csproj file. This element configures how the compiler interprets the nullability of types and what warnings are generated. Valid settings are:

  • enable:
    • The nullable annotation context is enabled. The nullable warning context is enabled.
    • Variables of a reference type, string for example, are non-nullable. All nullability warnings are enabled.
  • warnings:
    • The nullable annotation context is disabled. The nullable warning context is enabled.
    • Variables of a reference type are oblivious. All nullability warnings are enabled.
  • annotations:
    • The nullable annotation context is enabled. The nullable warning context is disabled.
    • Variables of a reference type, string for example, are non-nullable. All nullability warnings are disabled.
  • disable:
    • The nullable annotation context is disabled. The nullable warning context is disabled.
    • Variables of a reference type are oblivious, just like earlier versions of C#. All nullability warnings are disabled.

In your .csproj file, simply add <Nullable>enable</Nullable> in the relevant <PropertyGroup> element (your project file may have separate <PropertyGroup> elements for each project configuration name).

So your project file should look like this one:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

To display the nullable messages as errors instead of warnings, add this to your project file:

<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>

...like so:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <Nullable>enable</Nullable>
    <WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
  </PropertyGroup>

</Project>

The corresponding full messages are:

  • CS8600: Converting null literal or possible null value to non-nullable type.
  • CS8602: Possible dereference of a null reference.
  • CS8603: Possible null reference return.

You can also use directives to set these same contexts anywhere in your project:

  • #nullable enable: Sets the nullable annotation context and nullable warning context to enabled.
  • #nullable disable: Sets the nullable annotation context and nullable warning context to disabled.
  • #nullable restore: Restores the nullable annotation context and nullable warning context to the project settings.
  • #nullable disable warnings: Set the nullable warning context to disabled.
  • #nullable enable warnings: Set the nullable warning context to enabled.
  • #nullable restore warnings: Restores the nullable warning context to the project settings.
  • #nullable disable annotations: Set the nullable annotation context to disabled.
  • #nullable enable annotations: Set the nullable annotation context to enabled.
  • #nullable restore annotations: Restores the annotation warning context to the project settings.

By default, nullable annotation and warning contexts are disabled. That means that your existing code compiles without changes and without generating any new warnings.

Note that pre-release versions of C# 8.0 and Visual Studio 2019 also supported safeonly, however this option has since been removed and is not present in the final shipping C# 8.0. Additionally the pre-release versions used #pragma warning restore nullable but the released version uses #nullable restore warnings.

Solution 2:

I got this same error too, and I spent a few days fighting it, for a reason not described by the other answers: There are special (undocumented?) rules in the Roslyn C# compiler for generated code that uses the nullable feature, and until I upgraded Visual Studio 2019 to the latest version (16.4+), the error message was exactly the same unhelpful message as above — despite having <Nullable>enabled</Nullable> in my project file.

But in the latest versions of Visual Studio 2019, they've upgraded the error message to this:

warning CS8669: The annotation for nullable reference types should only be used in code within a ‘#nullable’ annotations context. Auto-generated code requires an explicit ‘#nullable’ directive in source.

(Emphasis added to the newly-added part of the error message.)

So if you're seeing this error message in any .generated.cs files you're emitting, those files need to have #nullable enable added to them explicitly — Roslyn apparently always ignores the project-level <Nullable>enable</Nullable> setting for generated code.