Skip to content

Fix module import failure when a newer Admin version is installed #58

@MariusStorhaug

Description

The Fonts module depends on the Admin module. Three public functions use #Requires -Modules with RequiredVersion, which demands an exact version match. When a newer version of Admin is installed (e.g., 1.1.13), Import-Module Fonts fails because the exact pinned version (1.1.6) is not found.

This is a blocking issue on PowerShell 7.5+ where module auto-update behavior and side-by-side version loading interact poorly with exact version pins.

Originally reported by Michael Kriese (@viceice) in #51.

Request

What happens

When a user has a newer version of Admin (e.g., 1.1.13) installed without the exact pinned version (1.1.6) also present, importing Fonts fails:

Import-Module Fonts
Import-Module: The module manifest 'Admin.psm1' could not be processed because it is not a valid
PowerShell module manifest file. Remove the elements that are not permitted:
[...]PowerShell\Modules\Admin\1.1.6\Admin.psd1

Even when both versions are installed side by side, the behavior is unreliable on PowerShell 7.5+.

What is expected

Newer versions of Admin should satisfy the dependency constraint. The #Requires directives should specify a minimum version, not an exact version, so that any version equal to or greater than the stated version is accepted.

Environment

  • Fonts module version: 1.1.26
  • Admin module version: 1.1.13 (pinned to 1.1.6 in #Requires)
  • PowerShell: 7.5.4 (Core)
  • OS: Windows 10.0.26100

Regression

This was not previously noticeable because the Admin module had not been updated beyond the pinned version. It became a problem once Admin released newer versions.

Workaround

Manually install the exact pinned version of Admin (1.1.6) alongside the newer version. This is fragile and defeats the purpose of semantic versioning.

Acceptance criteria

  • Import-Module Fonts succeeds when the installed version of Admin is equal to or newer than the minimum required version
  • All #Requires directives use ModuleVersion (minimum version) instead of RequiredVersion (exact version), with MaximumVersion added to cap the dependency at the 1.x major version range
  • No change in behavior when the exact pinned version is installed

Related


Technical decisions

Directive syntax: Change from RequiredVersion to ModuleVersion + MaximumVersion in the #Requires -Modules hashtable. ModuleVersion specifies the minimum acceptable version and MaximumVersion caps the range at the current major version (1.999.999), preventing a future Admin v2.0.0 from being loaded automatically.

Minimum version: Kept at 1.1.6 — the version originally specified. There is no reason to bump the floor since 1.1.6 is a known-good version and any newer minor/patch release remains compatible. The MaximumVersion = '1.999.999' constraint provides the upper bound, ensuring only 1.x versions are accepted.

Note

Why ModuleVersion + MaximumVersion (major-pinned range) instead of RequiredVersion (exact pin):
Per the official PowerShell module manifest documentation, version constraints in both RequiredModules and #Requires -Modules support three strategies:

Key Behavior Risk
RequiredVersion Exact pin — only that version satisfies Causes "dependency hell" when any newer version is installed
ModuleVersion Minimum floor — any version ≥ value satisfies Works as long as the dependency honors SemVer, but does not guard against breaking major-version changes
ModuleVersion + MaximumVersion Major-pinned range — allows minor/patch, blocks next major Best protection when a future major version may introduce breaking changes

Exact pinning (RequiredVersion) should be avoided for published modules that follow SemVer. It is the root cause of this bug. The chosen strategy for this fix is the major-pinned range (ModuleVersion + MaximumVersion), which provides the best protection against both missing-version failures and accidental major-version breakage.

Affected files: Three public functions have the directive:

  • src/functions/public/Get-Font.ps1
  • src/functions/public/Install-Font.ps1
  • src/functions/public/Uninstall-Font.ps1

Future consideration: migrate from #Requires to manifest RequiredModules

The #Requires -Modules directive on individual function files is evaluated at script scope and does not cause Install-Module / Install-PSResource to auto-install dependencies. It only asserts presence at load time.

The module manifest RequiredModules key, by contrast:

  • Is resolved and auto-installed by the PowerShell Gallery when a user runs Install-Module Fonts
  • Provides a single, authoritative declaration of dependencies (no duplication across files)
  • Supports the same ModuleVersion / MaximumVersion / RequiredVersion syntax

Moving the Admin dependency declaration from per-file #Requires directives to RequiredModules in manifest.psd1 would eliminate duplication and give users automatic dependency resolution. This is tracked as a follow-up, not part of this fix.


Implementation plan

Core changes

  • In src/functions/public/Get-Font.ps1, change #Requires -Modules @{ ModuleName = 'Admin'; RequiredVersion = '1.1.6' } to #Requires -Modules @{ ModuleName = 'Admin'; ModuleVersion = '1.1.6'; MaximumVersion = '1.999.999' }
  • In src/functions/public/Install-Font.ps1, change #Requires -Modules @{ ModuleName = 'Admin'; RequiredVersion = '1.1.6' } to #Requires -Modules @{ ModuleName = 'Admin'; ModuleVersion = '1.1.6'; MaximumVersion = '1.999.999' }
  • In src/functions/public/Uninstall-Font.ps1, change #Requires -Modules @{ ModuleName = 'Admin'; RequiredVersion = '1.1.6' } to #Requires -Modules @{ ModuleName = 'Admin'; ModuleVersion = '1.1.6'; MaximumVersion = '1.999.999' }

Verification

  • Verify Import-Module Fonts succeeds with a newer version of Admin installed (e.g., 1.1.13+)
  • Verify Import-Module Fonts still succeeds with the exact minimum version (1.1.6) installed
  • Verify Get-Font, Install-Font, and Uninstall-Font function correctly after the change

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions