Skip to content

[BUG]: Generating Scala3 uPickle from JSON Schema is missing ReadWriter annotation for enums #2677

Open

Description

@Bathtor

Issue Type

Output

Context (Environment, Version, Language)

Input Format: JSON Schema
Output Language: Scala3+uPickle

CLI, npm, or app.quicktype.io: CLI
Version: 23.0.170

Description

In the generated Scala3 output there is a missing ReadWriter annotation for the generated enum Color, which leads to a build failure while the uPickle macro is trying run:

No given instance of type ReadersVersionSpecific_this.Reader[
[error]     | quicktype.Color] was found.

Input Data

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "definitions": {
    "Color" : {
      "type" : "string",
      "enum": ["Red", "Green", "Blue"]
    },
    "Monster" : {
      "type" : "object",
      "properties" : {
        "name" : {
                "type" : "string"
              },
        "color" : {
                "$ref" : "#/definitions/Color"
              }
      },
      "required" : ["name", "color"],
      "additionalProperties" : false
    }
  },
  "$ref" : "#/definitions/Monster"
}

Expected Behaviour / Output

package quicktype

import upickle.default.*

case class Monster (
    val color : Color,
    val name : String
) derives ReadWriter 

enum Color derives ReadWriter :  
	 case Blue,Green,Red

Current Behaviour / Output

package quicktype

import upickle.default.*

case class Monster (
    val color : Color,
    val name : String
) derives ReadWriter 

enum Color :  
	 case Blue,Green,Red

Steps to Reproduce

It also reproduces in the webapp, so easiest repro is:

  1. paste above json into webapp and JSON Schema as source
  2. Select Scala3 and uPickle as target
  3. Try to compile the resulting code with with a minimal sbt project. Something along the lines of:
val scala3Version = "3.6.2"

lazy val root = project
  .in(file("."))
  .settings(
    name := "Quicktype Test",
    version := "0.1.0-SNAPSHOT",
    
    scalaVersion := scala3Version,
    libraryDependencies += "com.lihaoyi" %%% "upickle" % "4.1.0"
  )

Possible Solution

Just adjust the generator to add the necessary derive for enums.

Activity

  1. schani commented on Jul 6, 2026

    @schani
    Member

    Triage sweep note (assisted by Claude): confirmed reproducible on current master (v23.3.0, 68ecb284).

    Root cause: confirmed exactly as reported — output is enum Color : with no derives ReadWriter, while the corresponding case class correctly gets derives ReadWriter. UpickleRenderer (packages/quicktype-core/src/language/Scala3/UpickleRenderer.ts) only overrides emitClassDefinitionMethods; enum emission falls through to the base Scala3Renderer.emitEnumDefinition (Scala3Renderer.ts:298), which hardcodes ["enum ", name, " : "] with no hook for a derives clause. At runtime this fails with No given instance of type Reader[Color] since uPickle has no way to derive a Reader/Writer for the enum. CirceRenderer is unaffected because it fully overrides emitEnumDefinition itself.

    Assessment: severity medium — only affects the non-default --framework upickle option, but for that framework any schema containing an enum produces code that fails to compile/run, with no workaround. Fix difficulty: easy — add an overridable hook in the base renderer (e.g. an enum-declaration-suffix method) and have UpickleRenderer emit derives ReadWriter through it, mirroring the class-side handling.

    Reproduction:

    node dist/index.js --lang scala3 --src-lang schema --framework upickle monster.schema.json
    
    {
      "$schema": "https://json-schema.org/draft/2019-09/schema",
      "definitions": {
        "Color" : { "type" : "string", "enum": ["Red", "Green", "Blue"] },
        "Monster" : {
          "type" : "object",
          "properties" : {
            "name" : { "type" : "string" },
            "color" : { "$ref" : "#/definitions/Color" }
          },
          "required" : ["name", "color"],
          "additionalProperties" : false
        }
      },
      "$ref" : "#/definitions/Monster"
    }

    Output:

    case class MonsterSchema (
        val color : Color,
        val name : String
    ) derives ReadWriter 
    
    enum Color :  
    	 case Blue,Green,Red

    (enum Color is missing derives ReadWriter, matching the issue's expected-vs-actual.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions