Skip to content

Fix startup crash when published as self-contained single-file executable - #1436

Merged
iceljc merged 2 commits into
SciSharp:masterfrom
m-sekhon:fix/plugin-loader-single-file-publish
Sep 16, 2026
Merged

iceljc merged 2 commits into
SciSharp:masterfrom
m-sekhon:fix/plugin-loader-single-file-publish

Conversation

@m-sekhon

@m-sekhon m-sekhon commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Problem

PluginLoader.Load() derived its plugin search directory from Assembly.GetEntryAssembly().Location:

_executingDir = Directory.GetParent(Assembly.GetEntryAssembly().Location).FullName;

.NET leaves Location empty ("") when the app is published as a self-contained, single-file executable (-p:PublishSingleFile=true --self-contained true). Directory.GetParent("") then throws, crashing the app before it can even start:

Unhandled exception. System.ArgumentException: The value cannot be an empty string. (Parameter 'path')
   at System.ArgumentException.ThrowNullOrEmptyException(String argument, String paramName)
   at System.IO.Directory.GetParent(String path)
   at BotSharp.Core.Plugins.PluginLoader.Load(Action`1 loaded, String plugin)
   at BotSharp.Core.BotSharpCoreExtensions.RegisterPlugins(IServiceCollection services, IConfiguration config)
   at BotSharp.Core.BotSharpCoreExtensions.AddBotSharpCore(IServiceCollection services, IConfiguration config, Action`1 configOptions)
   at Program.<Main>$(String[] args)

Fixes #669

Fix

Use AppContext.BaseDirectory instead, which resolves correctly for both regular and single-file-published deployments.

Verification

  • Reproduced the original crash by publishing with dotnet publish -r linux-x64 --self-contained true -p:PublishSingleFile=true and running the resulting binary directly — got the exact stack trace from Publish exception #669.
  • Confirmed the fix resolves it — same publish/run steps after the change start the app cleanly instead of crashing.
  • dotnet run (the documented dev workflow) verified unaffected before and after.
  • Added two regression tests in tests/BotSharp.Core.UnitTests/Plugins/PluginLoaderTests.cs:
    • asserts Load() doesn't throw and that the resolved executing directory matches AppContext.BaseDirectory
    • asserts it can still find and load a real plugin assembly from that directory
  • Full BotSharp.Core.UnitTests suite passes: 376/376.

PluginLoader.Load() derived the plugin search directory from
Assembly.GetEntryAssembly().Location, which .NET leaves empty when
the app is published with PublishSingleFile + self-contained. That
made Directory.GetParent("") throw an ArgumentException before the
app could even start.

Use AppContext.BaseDirectory instead, which resolves correctly for
both regular and single-file-published deployments.

Fixes SciSharp#669
Covers the fix in the previous commit for SciSharp#669: verifies
PluginLoader.Load() resolves its executing directory from
AppContext.BaseDirectory (not Assembly.GetEntryAssembly().Location),
and that it can still find and load a real plugin assembly from
that directory.
@qodo-code-review

Copy link
Copy Markdown
Contributor

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@iceljc
iceljc merged commit 83f518f into SciSharp:master Sep 16, 2026
1 of 4 checks passed
@m-sekhon
m-sekhon deleted the fix/plugin-loader-single-file-publish branch September 16, 2026 20:33
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.

Publish exception

2 participants