Skip to content

Fix ArgumentNullException ("input") during publish for non-.NET runtimes (latent bug exposed by v4.7.0)#4827

Merged
liliankasem merged 6 commits intomainfrom
copilot/investigate-null-input-error
Mar 16, 2026
Merged

Fix ArgumentNullException ("input") during publish for non-.NET runtimes (latent bug exposed by v4.7.0)#4827
liliankasem merged 6 commits intomainfrom
copilot/investigate-null-input-error

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 11, 2026

func azure functionapp publish throws ArgumentNullException: Value cannot be null. (Parameter 'input') for all non-.NET runtimes (PowerShell, Node.js, Python, Java) on Windows function apps when --dotnet-version is not specified.

Root Cause

The true root cause is a latent bug introduced in July 2021 by PR #2639, which refactored UpdateFrameworkVersions and accidentally widened the scope of UpdateNetFrameworkVersionWindows from DotnetIsolated-only to all non-DotnetIsolated Windows apps. Before that refactor, UpdateNetFrameworkVersionWindows was only reachable through UpdateDotNetIsolatedFrameworkVersion, which gates on workerRuntime == DotnetIsolated. The refactor added an else if (!functionApp.IsLinux) branch at the top level of UpdateFrameworkVersions that caught every Windows runtime — PowerShell, Node, Python, Java — and routed them into dotnet-specific version update logic they had no business entering.

This was silently masked for over three years because _requiredNetFrameworkVersion defaulted to "8.0", so NormalizeDotnetFrameworkVersion(null) would fall back to new Version("8.0") and harmlessly (but incorrectly) set NetFrameworkVersion=v8.0 on the function app — a property Azure ignores for non-.NET runtimes.

PR #4760 (v4.7.0) exposed the bug by correctly changing the default to null for dynamic TFM detection. With no fallback, new Version(null) throws ArgumentNullException: Value cannot be null. (Parameter 'input').

Fix

  • UpdateFrameworkVersions — removed the erroneous else if (!functionApp.IsLinux) branch, restoring the intended structure where only DotnetIsolated enters UpdateNetFrameworkVersionWindows (via UpdateDotNetIsolatedFrameworkVersion)
  • NormalizeDotnetFrameworkVersion — returns null instead of throwing when both inputs are null (belt-and-suspenders)
  • UpdateNetFrameworkVersionWindows — returns early if normalizedVersion == null (belt-and-suspenders)
  • DotnetIsolatedLinuxValidation — same null guard added for consistency (belt-and-suspenders)
// Before (PR #2639 regression): all non-.NET Windows apps routed into dotnet-specific logic
if (workerRuntime == WorkerRuntime.DotnetIsolated)
{
    await UpdateDotNetIsolatedFrameworkVersion(...);
}
else if (!functionApp.IsLinux)  // ← erroneous branch: caught PowerShell, Node, Python, Java
{
    await UpdateNetFrameworkVersionWindows(...);
}

// After: only DotnetIsolated reaches UpdateNetFrameworkVersionWindows
if (workerRuntime == WorkerRuntime.DotnetIsolated)
{
    await UpdateDotNetIsolatedFrameworkVersion(...);
}
// non-.NET Windows apps fall through with no dotnet version update — correct behaviour

Issue describing the changes in this PR

resolves #4822

Pull request checklist

  • My changes do not require documentation changes
    • Otherwise: Documentation issue linked to PR
  • My changes do not need to be backported to a previous version
    • Otherwise: Backport tracked by issue/PR #issue_or_pr
  • My changes should not be added to the release notes for the next release
    • Otherwise: I've added my notes to release_notes.md
  • I have added all required tests (Unit tests, E2E tests)

Additional information

Unit tests cover all four affected runtimes (PowerShell, Node, Python, Java):

  • UpdateFrameworkVersions_NonDotnetWindowsApp_NoDotnetVersion_DoesNotCallUpdateWebSettings — verifies no web settings update occurs when no --dotnet-version is specified
  • UpdateFrameworkVersions_NonDotnetWindowsApp_ExplicitDotnetVersion_DoesNotUpdateWebSettings — verifies that even an explicit --dotnet-version is correctly ignored for non-.NET runtimes
  • UpdateFrameworkVersions_NonDotnetLinuxApp_NoDotnetVersion_DoesNotThrow — verifies the Linux non-.NET path is also safe
Original prompt

This section details on the original issue you should resolve

<issue_title>Value cannot be null. (Parameter 'input') during publish after upgrade to v4.7.0</issue_title>
<issue_description>### Version

4.7.0

Description

When running

func azure functionapp publish <app name> --verbose

The output is Value cannot be null. (Parameter 'input'). No additional information on what's missing. I tried adding / removing values from local.settings.json and it still reproduces.
Confirmed this is not an issue with version v4.6.0 and it started with v4.7.0

Might be a specific issue to my configuration, but the error isn't indicative to say so.

Steps to reproduce

  1. Install v4.7.0.
  2. Try to publish your app.
  3. Output should be Value cannot be null. (Parameter 'input')</issue_description>

<agent_instructions>Investigate this regresssion that started with 4.7.0 and propose a solution to the issue</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@liliankasem
Copy link
Copy Markdown
Member

@copilot

Identify root cause: new Version(null) in NormalizeDotnetFrameworkVersion throws ArgumentNullException: Value cannot be null. (Parameter 'input') when both version and _requiredNetFrameworkVersion are null

What change occured in 4.7.0 that led to this? Point me to the commit/PR for this

Copilot AI and others added 2 commits March 11, 2026 20:58
…ilure for non-.NET runtimes

Co-authored-by: liliankasem <2198905+liliankasem@users.noreply.github.com>
Co-authored-by: liliankasem <2198905+liliankasem@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix value cannot be null error during publish after upgrade to v4.7.0 Fix ArgumentNullException ("input") during publish for non-.NET runtimes (v4.7.0 regression) Mar 11, 2026
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 11, 2026

@copilot

Identify root cause: new Version(null) in NormalizeDotnetFrameworkVersion throws ArgumentNullException: Value cannot be null. (Parameter 'input') when both version and ...

The regression was introduced in PR #4760 ("Add EOL warnings for all runtimes during function app publish"), specifically this one-line change:

- private static string _requiredNetFrameworkVersion = "8.0";
+ private static string _requiredNetFrameworkVersion = null;

In v4.6.0, _requiredNetFrameworkVersion defaulted to "8.0". So when NormalizeDotnetFrameworkVersion(null) was called (no --dotnet-version provided, non-.NET runtime), it fell back to new Version("8.0") which succeeded.

In v4.7.0 (post-#4760), the default was changed to null since TFM detection now reads the actual project file. But for non-.NET runtimes (PowerShell, Node, Python, Java), _requiredNetFrameworkVersion is never set (the DotnetIsolated-only detection block is skipped), so new Version(null) throws ArgumentNullException: Value cannot be null. (Parameter 'input').

The intent of the change was correct — auto-detect TFM instead of hardcoding 8.0 — but it needed guards for the non-.NET case. The fix in this PR adds those guards: NormalizeDotnetFrameworkVersion returns null when both inputs are null, and the callers skip the update gracefully.

@liliankasem
Copy link
Copy Markdown
Member

@copilot

The ArgumentNullException during func azure functionapp publish for non-.NET runtimes (PowerShell, Node.js, Python, Java) on Windows is a latent bug introduced in July 2021 by PR #2639, which refactored UpdateFrameworkVersions and accidentally widened the scope of UpdateNetFrameworkVersionWindows from DotnetIsolated-only to all non-DotnetIsolated Windows apps. Before that refactor, UpdateNetFrameworkVersionWindows was only reachable through UpdateDotNetIsolatedFrameworkVersion, which gates on workerRuntime == DotnetIsolated. The refactor added an else if (!functionApp.IsLinux) branch at the top level of UpdateFrameworkVersions that caught every Windows runtime — PowerShell, Node, Python, Java — and routed them into dotnet-specific version update logic they had no business entering. This was silently masked for over three years because _requiredNetFrameworkVersion defaulted to "8.0", so NormalizeDotnetFrameworkVersion(null) would fall back to new Version("8.0") and harmlessly (but incorrectly) set NetFrameworkVersion=v8.0 on the function app — a property Azure ignores for non-.NET runtimes. When PR #4760 (v4.7.0) correctly changed the default to null for dynamic TFM detection, the mask came off: new Version(null) throws ArgumentNullException. This fix removes the erroneous branch entirely, restoring UpdateFrameworkVersions to its intended structure where only DotnetIsolated enters UpdateNetFrameworkVersionWindows (via UpdateDotNetIsolatedFrameworkVersion), and adds defensive null guards in NormalizeDotnetFrameworkVersion, UpdateNetFrameworkVersionWindows, and DotnetIsolatedLinuxValidation as belt-and-suspenders protection.

Update the PR description and title to reflect the updated fix

@liliankasem liliankasem marked this pull request as ready for review March 11, 2026 23:27
@liliankasem liliankasem requested a review from a team as a code owner March 11, 2026 23:27
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 11, 2026

@copilot

The ArgumentNullException during func azure functionapp publish for non-.NET runtimes (PowerShell, Node.js, Python, Java) on Windows is a latent bug introduced in July 20...

Updated the PR title, description, and release notes in commit 435c3cd to reflect the complete root cause analysis:

Latent bug (PR #2639, July 2021): UpdateFrameworkVersions was refactored to add an else if (!functionApp.IsLinux) branch that caught all non-DotnetIsolated Windows apps — including PowerShell, Node, Python, and Java — routing them into UpdateNetFrameworkVersionWindows which is pure dotnet logic. Before that refactor, UpdateNetFrameworkVersionWindows was only reachable through UpdateDotNetIsolatedFrameworkVersion (which gates on workerRuntime == DotnetIsolated).

Why it was masked (2021–2024): _requiredNetFrameworkVersion defaulted to "8.0", so NormalizeDotnetFrameworkVersion(null) would fall back to new Version("8.0") and harmlessly set NetFrameworkVersion=v8.0 — a property Azure ignores for non-.NET runtimes.

v4.7.0 exposed it (PR #4760): _requiredNetFrameworkVersion was correctly changed to null for dynamic TFM detection. With no fallback, new Version(null) throws ArgumentNullException.

Primary fix: Removed the erroneous else if (!functionApp.IsLinux) branch, restoring UpdateFrameworkVersions to its intended structure where only DotnetIsolated enters UpdateNetFrameworkVersionWindows. The null guards in NormalizeDotnetFrameworkVersion, UpdateNetFrameworkVersionWindows, and DotnetIsolatedLinuxValidation remain as belt-and-suspenders protection.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • azfunc.pkgs.visualstudio.com
    • Triggering command: /usr/bin/dotnet dotnet test test/Cli/Func.UnitTests/Azure.Functions.Cli.UnitTests.csproj --filter PublishFunctionAppAction --no-restore -v minimal (dns block)
    • Triggering command: /usr/bin/dotnet dotnet restore test/Cli/Func.UnitTests/Azure.Functions.Cli.UnitTests.csproj (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Fix ArgumentNullException ("input") during publish for non-.NET runtimes (v4.7.0 regression) Fix ArgumentNullException ("input") during publish for non-.NET runtimes (latent bug exposed by v4.7.0) Mar 11, 2026
@liliankasem
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@liliankasem liliankasem merged commit 6acc224 into main Mar 16, 2026
39 checks passed
@liliankasem liliankasem deleted the copilot/investigate-null-input-error branch March 16, 2026 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Value cannot be null. (Parameter 'input') during publish after upgrade to v4.7.0

3 participants