Skip to content

cabalSpecLatest remains 3.16 in cabal-install 3.18.1.0, causing cabal-version: 3.18 Simple packages to fail #12271

Closed

Description

@andreabedini

Describe the bug

Cabal-syntax 3.18.1.0 defines and parses CabalSpecV3_18. However, cabalSpecLatest remains CabalSpecV3_16.

This mismatch changes the behaviour of cabal-install. packageSetupScriptStyle treats any non-Custom, non-Hooks package above cabalSpecLatest as a future-format package.

A normal package with cabal-version: 3.18 therefore receives SetupNonCustomExternalLib, not SetupNonCustomInternalLib.

For example, this expression returns SetupNonCustomExternalLib:

packageSetupScriptStyle
  (emptyPackageDescription {specVersion = CabalSpecV3_18})

The expected result is SetupNonCustomInternalLib. cabal-install 3.18.1.0 links against a Cabal library that supports specification 3.18.

Explicit .cabal parsing recognises cabal-version: 3.18. The problem is the stale default and code that uses it as the supported-version boundary.

To reproduce

Use cabal-install 3.18.1.0:

$ cabal --version
cabal-install version 3.18.1.0
compiled using version 3.18.1.0 of the Cabal library

Create repro.cabal:

cabal-version: 3.18
name:          repro
version:       0.1.0.0
build-type:    Simple

executable repro
  main-is:          Main.hs
  build-depends:    base
  default-language: Haskell2010

Create Main.hs:

main :: IO ()
main = putStrLn "ok"

Use an empty setup-executable cache. An existing cache entry can otherwise hide the problem.

setup_cache=$(mktemp -d)

XDG_CACHE_HOME="$setup_cache" cabal build --dry-run
# Succeeds

XDG_CACHE_HOME="$setup_cache" cabal build
# Fails

The failure starts approximately as follows:

[1 of 2] Compiling Main (.../setup/setup.hs, .../setup/Main.o)

setup/setup.hs:2:1: error:
    Could not load module ‘Distribution.Simple’.
    It is a member of the hidden package ‘Cabal-...’.

The failing Main module is the generated setup wrapper, not the package's Main.hs.

Expected behaviour

The full build must succeed.

A Simple package with cabal-version: 3.18 must use SetupNonCustomInternalLib in cabal-install 3.18.1.0.

What happens internally

  1. The release recognizes CabalSpecV3_18, but cabalSpecLatest remains CabalSpecV3_16.
  2. packageSetupScriptStyle therefore classifies the package as SetupNonCustomExternalLib.
  3. mkDefaultSetupDeps computes an implicit dependency on Cabal >= 3.17.
  4. setImplicitSetupInfo materializes implicit setup information only for Custom and Hooks.
  5. It therefore discards the computed dependency for the Simple package.
  6. The solver sees no setup dependency, so --dry-run succeeds.
  7. The elaborated plan nevertheless retains SetupNonCustomExternalLib.
  8. During execution, cabal compiles the generated Setup.hs with an empty exclusive dependency set.
  9. The generated setup wrapper cannot import Distribution.Simple, so the build fails.

Change only the declared specification version:

-cabal-version: 3.18
+cabal-version: 3.16

The full build then succeeds.

Proposed fix

  • Publish a Cabal-syntax 3.18 patch release with:

    cabalSpecLatest = CabalSpecV3_18
  • Publish a cabal-install patch release with binaries built against the corrected Cabal-syntax release.

The 3.18 release branch must advance only to CabalSpecV3_18.

Current master also defines CabalSpecV3_20 and contains features gated by it. The corresponding change on master must advance cabalSpecLatest to CabalSpecV3_20.

Activity

  1. ffaf1 commented on Aug 24, 2026

    @ffaf1
    Collaborator

    Depressing bug.

    A check has to land in CI/checklist too, otherwise we are bound to repeat the mistake.

  2. added 3 commits that reference this issue on Aug 24, 2026
    2a4c100
    a290081
    4b124ed
  3. changed the title [-]> cabalSpecLatest remains 3.16 in cabal-install 3.18.1.0, causing cabal-version: 3.18 Simple packages to fail[/-] [+]cabalSpecLatest remains 3.16 in cabal-install 3.18.1.0, causing cabal-version: 3.18 Simple packages to fail[/+] on Aug 24, 2026
  4. andreabedini commented on Aug 24, 2026

    @andreabedini
    CollaboratorAuthor

    A check has to land in CI/checklist too, otherwise we are bound to repeat the mistake.

    Yes, I was thinking about how to test this in CI. Of the top of my head I cannot think of a reason to not simply use cabalSpecLatest = maxBound? (there must be a reason just I cannot think of one :)

  5. andreabedini commented on Aug 26, 2026

    @andreabedini
    CollaboratorAuthor

    @ffaf1 Notice I tried to document the proper procedure in #12056

  6. added a commit that references this issue on Sep 7, 2026
    cc36041
  7. jeffstyr commented on Sep 13, 2026

    @jeffstyr

    Testing that cabal init --non-interactive && cabal build succeeds would be a good functional test to add. (It's particularly embarrassing when following the "Getting Started" guide fails with a strange error.)

  8. emilypi commented on Sep 14, 2026

    @emilypi
    Member

    @jeffstyr I agree with you there. The --non-interactive workflow has exactly one goal: it should be the fastest means to a project that compiles and/or runs available to the user, with a --simple being both the fastest and most minimal means to a project that compiles and/or runs. We need regression tests need to reflect that goal. If you want we can assign this one to me and I can get it set up.

  9. ulysses4ever commented on Sep 15, 2026

    @ulysses4ever
    Collaborator

    has this been fixed in

    if so, should we close?

  10. zlonast commented on Sep 21, 2026

    @zlonast
    Collaborator

    @ulysses4ever This fix went only into the 3.18 branch.

  11. ulysses4ever commented on Sep 21, 2026

    @ulysses4ever
    Collaborator

    @zlonast correct. Now, let’s read the title of the issue… I think either this issue isn’t relevant beyond 3.18 or the title should be generalized to cover other versions.

  12. added a commit that references this issue on Oct 7, 2026
    caaf6b5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions