Good First Issues in Scala
Explore curated starter issues in high-scoring Scala repositories. Every listed issue belongs to a welcoming repository scored by C-Rankβ’ on PR merge rates, review responsiveness, and first-timer acceptance.
Arm Issue Sniper for fresh Scala beginner issues
Beginner issues in welcoming S/A-Tier repositories get snatched within 15 minutes. Receive instant alerts on Discord, Telegram, or Email the minute a maintainer opens a new task.
Live Good First Issues (30)
Real-Time Open GitHub IssuesProviderExchangeSinkSpec (modules/core/src/test/scala/.../provider/ProviderExchangeSinkSpec.scala) creates temporary directories and files with the prefixes provider-exchange-dir, -collision, -parallel, -read-only and -not-dir, and never deletes them. On a developer machine they pile up in $TMPDIR (about 440 found after a day of test runs). What to do: delete everything each test creates, even when the test fails. Use a small helper that creates a temp directory, runs the test body, and then deletes the directory recursively. The read-only case must restore write permission first so the delete works. scalafix bans try/finally in main code, but test code may use scala.util.Using or ultimately from scala.util.control.Exception. Check afterwards that a test run leaves no provider-exchange-* entries in $TMPDIR.
ToolRegistry's retry backoff has no jitter. ToolRegistry.retryDelay (modules/core/src/main/scala/org/llm4s/toolapi/ToolRegistry.scala) returns ToolRetryPolicy.delayBeforeAttempt(attempt) exactly. Many clients retrying a failing tool on the same fixed schedule therefore hit the backend again at the same moment, which makes a load spike or a rate limit worse (a thundering herd). @vim89 raised this in review of #1197; it was left out of #1426. Proposal: Add optional jitter to ToolRetryPolicy, for example withJitter(fraction: Double) with "full" or "equal" jitter, as in AWS's backoff guidance. Keep the default at no jitter, so existing behaviour and tests are unchanged. ToolRetryPolicy is a growth-prone data type, so follow the CLAUDE.md pattern for adding a field: add it to the constructor and to apply with a default, keep the previous apply as an overload, and add a withX setter. Use an injectable random source, so tests are deterministic. Clamp the jittered delay to [0, maxDelay]. Tes
Add SoftwareApp schema (Google, full spec) to the /app page. { "@context": "https://schema.org", "@type": "MobileApplication", "name": "Lichess", "operatingSystem": "Android, iOS", "applicationCategory": "GameApplication", "releaseNotes": "https://github.com/lichess-org/mobile/releases", "screenshot": "", // use assetUrl("images/mobile/lichess-mobile-screen.webp") "url": "https://lichess.org/app", "offers": [ { "@type": "Offer", "price": 0, "name": "Google Play", "url": "https://play.google.com/store/apps/details?id=org.lichess.mobileV2" }, { "@type": "Offer", "price": 0, "name": "F-Droid", "url": "https://f-droid.org/packages/org.lichess.mobileV2" }, { "@type": "Offer", "price": 0, "name": "App Store", "url": "https://apps.apple.com/app/lichess/id1662361230" } ], "aggregateRating": { "@type": "AggregateRating", "ratingCount": 2895, "ratingValue": 4.2 // we
Context The README and CONTRIBUTING.md give different days for the weekly contributor session ("Dev Hour"): CONTRIBUTING.md (line 99): "We host a contributor dev hour on Discord every Tuesday at 17:00 UTC." README.md (lines 601 and 608): "join us every Sunday on Discord!" and "Weekly Sundays" in the schedule table, with no time given. A newcomer who reads one page will turn up on the wrong day. Only a maintainer knows the real schedule. Task Ask in the issue (or on Discord) which day and time is current, and wait for a maintainer to confirm it. Do not guess. Make both files say the same thing, in the same words, with the day, the time and the time zone. Check the other places that mention the session (git grep -in "dev hour" -- README.md CONTRIBUTING.md docs) and fix any that still disagree. Acceptance criteria README.md, CONTRIBUTING.md and any docs page that mentions Dev Hour give the same day and time. The maintainer's confirmation is linked in the pull request. scripts/check-d
Problem The @example in the class Scaladoc of RAG (modules/rag/src/main/scala/org/llm4s/rag/RAG.scala, around lines 36 to 58) builds a pipeline with RAG.builder().withEmbeddings("openai")...build().toOption.get. That does not compile as shown. build on a RAGConfig is an extension supplied by implicit class RAGConfigOps inside object RAG (line 1552, def build(using ModelRegistryService, ProviderRegistry): Result[RAG]), so a caller needs import org.llm4s.rag.RAG.RAGConfigOps and a ModelRegistryService and a ProviderRegistry in scope. Without the import the compiler reports value build is not a member of org.llm4s.rag.RAGConfig. The build method also takes only a using clause, so the build() spelling with empty parentheses in the example should be checked too. docs/guide/permission-based-rag.md is the one page that shows the import (lines 61 and 633). docs/reference/migration.md and docs/design/web-crawler-loader.md also use RAG.builder(); check them for the same omission. Found while com
Problem Llm4sHttpClientSpec (modules/core/src/test/scala/org/llm4s/http/Llm4sHttpClientSpec.scala, the "Llm4sHttpClient.close ... a later request is a Left" test, around line 263) asserts behaviour that exists only on JDK 21: java.net.http.HttpClient#close() is new in 21, and Llm4sHttpClient.close() is a deliberate no-op on earlier JDKs. On JDK 17 the test fails (the second request still succeeds). The spec has no JDK guard, so it is only green because CI runs JDK 21 alone. Found while running core's tests on a real JDK 17 for #1581: 1,968 passed and this one failed. Proposal Guard the assertion on Runtime.version().feature() >= 21 (assume/cancel, so it shows as skipped, not passed, on 17), and add a short comment saying why. This matters only if a JDK 17 job is ever added to CI (see #1493), but it keeps the suite honest before then. Acceptance criteria On JDK 17 the test is cancelled with a clear reason; on JDK 21 it runs and passes unchanged.
Problem The documentation site is built without the jekyll-relative-links plugin, so a relative link that ends in .md is served as-is and returns 404. Checked with curl on 2026-10-08: https://llm4s.org/getting-started/configuration.md returns 404, and https://llm4s.org/getting-started/configuration returns 200. A trailing slash (.../configuration/) is also 404. Many pages link in the .md form, for example docs/guide/basic-usage.md (../getting-started/configuration.md#named-provider-sections) and docs/guide/error-handling.md. The whole-docs link check proposed in #1573 found 68 such links when run over docs/ (it records them in its baseline under the cause md-extension). A reader clicking any of them lands on a 404 page, although the same link works on GitHub, which is why it goes unnoticed in review. Proposal Remove the .md extension from those relative links, keeping the #anchor (the anchors are unaffected). It is mechanical: for each link in the baseline of #1573 with cause md-extens
Context Two published modules have no README: modules/providers/bedrock (llm4s-bedrock, sbt project bedrock, the AWS Bedrock chat provider on the Converse and ConverseStream APIs) and modules/provider-testkit (llm4s-provider-testkit, project providerTestkit, the checks a provider module's Llm4s<Name>ModuleSpec runs, for external authors too). docs/reference/v1-scope.md lists both (Bedrock as Beta). Facts to build on: Bedrock: id bedrock, chat only (Llm4sBedrockModule overrides only chatProviders). Its reference.conf says there is no API key to share: it uses AWS credentials found by the AWS SDK (environment variables, ~/.aws, a role) unless the section names them, and region is required and never defaulted. A section can set model (a model id or an inference profile), region, profile, accessKeyId, secretAccessKey and sessionToken. There is a @Cloud smoke suite in modules/it; the module's own tests run without AWS. Testkit: ProviderModuleChecks, ProviderTestConfig, CredentialsRoundTrip
Context Every commit needs a Signed-off-by trailer: .github/workflows/dco.yml fails the pull request over a single unsigned commit, and CONTRIBUTING.md explains it in the "Developer Certificate of Origin (DCO)" section (line 9). Fixing it afterwards rewrites history and costs a force-push. The pull request template (.github/PULL_REQUEST_TEMPLATE.md) never mentions it: grep -ciE "sign|DCO" on the file prints 0, so a first-time contributor learns about the requirement from a red check. The checklist also omits sbt scalafixAll, which CONTRIBUTING.md lists as enforced. Task Add two items to the "Checklist" in .github/PULL_REQUEST_TEMPLATE.md, in the style of the existing ones: every commit is signed off (git commit -s), linking CONTRIBUTING.md sbt scalafixAll passes Keep the template short: do not add other items. Check that the anchor matches the heading in CONTRIBUTING.md. Acceptance criteria The template has the two new unchecked items and nothing else changes The link resolves to th
Context CONTRIBUTING.md documents sbt +compile as "Compile all versions" and sbt +test as "Run all tests" / "Run tests all versions" (lines 124, 125, 376 and 378), and says sbt buildAll is a "Full pipeline (compile + test all versions)". LLM4S is Scala 3 only: nothing assigns crossScalaVersions (git grep -nE "crossScalaVersions[[:space:]]*(:=|\+=)" finds nothing, while build.sbt line 18 sets scalaVersion := scala3), and buildAll is the alias ;clean;compile;test (build.sbt line 84). So the + form does the same as the plain command and the "all versions" wording is wrong. The Scala 2.13 discussion (#874, #888, #1095) started from exactly this kind of claim, and scripts/check-doc-support.sh now guards against it, but only for CLAUDE.md, README.md and docs/**/*.md (its FILES list, around line 122), so CONTRIBUTING.md and AGENTS.md are never checked. Task Fix CONTRIBUTING.md: replace the +compile and +test lines with the plain commands and describe buildAll as what it is (clean, compile, t
Context Nothing in the library reads LLM_MODEL: providers are named sections in application.conf, and Llm4sConfig.defaultProvider() loads the one that llm4s.providers.provider names (CLAUDE.md; the same sentence is in the ScalaDoc of Llm4sConfig.scala and ConfigKeys.scala). Three comments still say otherwise: modules/samples/src/main/scala/org/llm4s/samples/catseffect/CatsEffectAgentExample.scala lines 16 to 18 and .../zio/ZIOAgentExample.scala lines 16 to 18 say "Required environment: LLM_MODEL=openai/gpt-4o (or any supported provider), OPENAI_API_KEY=sk-...". Both samples get their client from LLMClientIO.resource / LLMClientZ.layer, which call Llm4sConfig.defaultProvider(); the samples' application.conf defaults to the ollama-local section, so following the header does not select OpenAI. modules/java-api/src/main/scala/org/llm4s/javaapi/Llm4s.scala lines 31 and 32 say createDefaultClient() uses a default provider "configured via environment variables (e.g. LLM_MODEL, OPENAI_API_KEY
Context Three places in the guides tell readers to call something that is not in the code. A search of every Scala snippet in docs/ for Object.method calls on objects defined in the main sources, and of every org.llm4s.samples.* name, found these (line numbers are from main at the time of writing; the guardrails guide is also being edited in an open pull request, so re-check them): docs/guide/agents/guardrails.md lines 296 and 320 use LLMError.validation(...) and line 346 uses LLMError.parsing(...), in the custom guardrail examples. LLMError has no such members (git grep -nE "def (validation|parsing)[ (\[]" finds only an unrelated test helper). The real constructors are ValidationError.invalid(field, reason) (modules/core/src/main/scala/org/llm4s/error/ValidationError.scala, line 43) and LLMError.processingFailed(operation, message) (LLMError.scala, line 86). docs/guide/rag-evaluation.md line 309 calls BenchmarkReport.saveJson(results, path). The method is BenchmarkReport.save(results
Context Providers are discovered from the classpath: each module declares an Llm4sProviderModule in META-INF/services, and ProviderRegistry.discover() collects them. The result carries a ProviderRegistryReport (registry.report: modules, failures, collisions, summary, describe) plus ids and embeddingIds. This is the first thing to check when "provider X is not registered" appears, for example in a shaded jar whose services files were overwritten (docs/guide/writing-a-provider.md explains this), yet no sample under modules/samples uses ProviderRegistry. It needs no API key. Task Add modules/samples/src/main/scala/org/llm4s/samples/basic/ProviderDiscoveryExample.scala that: calls ProviderRegistry.discover() and prints report.describe, ids and embeddingIds shows the contrast with an explicit registry: ProviderRegistry.ofModules(new Llm4sOllamaModule) has report.discovered == false and only the ids of that module says in comments what failures and collisions would mean and where to read mo
Background Most pages on the site currently have /feed.atom linked in the HTML, like so: <link href="/feed.atom" title="Lichess Updates Feed" type="application/atom+xml" rel="alternate" /> There are some important exceptions where we don't link the feed. This issue is focused on user blogs but there may be more. When it comes to blogs: All user blogs have feeds at /@/<username>/blog.atom. /blog/community has /blog/community.atom, which just has a plain link in the head <link href="/blog/community.atom" title="Lichess community blogs" /> Proposal For all user blog landing pages (example) and individual blog posts (example): Add a link to the user's blog feed e.g. <link href="/@/NDpatzer/blog.atom" title="NDpatzer's Blog" type="application/atom+xml" rel="alternate" />. For the title, return whatever the ublog.xBlog string for xml:lang is (following #21961) Crawlers may index the feeds of blog posts that are intended not to be indexed. To mitigate that risk*, add X-Robots-Tag: noinde
Describe the bug With the native from_json path enabled (spark.comet.expression.JsonToStructs.allowIncompatible=true), a schema that repeats a field name fails the task once the result reaches the JVM. Spark accepts such a schema and fills the last field with that name, so from_json('{"a":1}', 'a INT, a INT') returns {null, 1}. Comet's native projection builds the same struct, and to_json over it matches Spark, but importing the result on the JVM fails because Java Arrow keys struct children by name: java.lang.IllegalStateException: ArrowArray struct has 2 children (expected 1) at org.apache.arrow.util.Preconditions.checkState(Preconditions.java:562) at org.apache.arrow.c.ArrayImporter.doImport(ArrayImporter.java:92) at org.apache.arrow.c.ArrayImporter.importArray(ArrayImporter.java:68) at org.apache.arrow.c.ArrowImporter.importVector(ArrowImporter.java:62) at org.apache.comet.vector.NativeUtil.importVector(NativeUtil.scala:264) at org.apache.comet.vector.NativeUtil.getNextBatch(
Describe the bug A cast whose target struct type repeats a field name fails the task when Comet runs it natively. Spark allows the cast as long as each pair of fields casts, so CAST(s AS STRUCT<x: INT, x: INT>) over a STRUCT<p: INT, q: INT> column returns {1, 10}. Comet's native cast_struct_to_struct builds the result with the target fields, and the projection itself works: to_json over the cast matches Spark with {"x":1,"x":10}. Importing the result on the JVM then fails, because Java Arrow keys struct children by name and the two x children collapse into one: java.lang.IllegalStateException: ArrowArray struct has 2 children (expected 1) at org.apache.arrow.util.Preconditions.checkState(Preconditions.java:562) at org.apache.arrow.c.ArrayImporter.doImport(ArrayImporter.java:92) at org.apache.arrow.c.ArrayImporter.importChild(ArrayImporter.java:83) at org.apache.arrow.c.ArrayImporter.doImport(ArrayImporter.java:101) at org.apache.arrow.c.ArrayImporter.importArray(ArrayImporter.java
Context LLMClient.completeStructured[A] and LLMClient.extractJson (added in #977) are not described in any guide. The only trace is the StructuredOutputExample sample. Users need to know the behaviours that are not obvious from the signature. Task Add docs/guide/structured-output.md (and link it from docs/guide/index.md) covering: what completeStructured[A] does and a short example (see modules/samples/.../basic/StructuredOutputExample.scala) which providers enforce the schema natively (OpenAI, Gemini/Vertex, openai-compatible including Cohere, Ollama via its format field, which needs a recent Ollama) and that Anthropic is a best-effort prompt instruction, not schema-enforced that the schema is derived with strict = true, which makes every property required, including ones declared optional that a reply of JSON null, a non-object, or text that does not match the schema returns a ValidationError, and how fenced or prose-wrapped JSON is recovered by extractJson how options are forwarded
Context GeminiSmokeSpec (in modules/it/.../llmconnect/smoke/) still uses gemini-1.5-flash and reads only GEMINI_API_KEY. The new Gemini vision smoke test in #1037 uses gemini-2.0-flash and accepts either GOOGLE_API_KEY or GEMINI_API_KEY. gemini-1.5-flash may be retired, and having two Gemini suites that disagree on model and key handling is confusing for whoever runs sbt testSmoke. Neither model name was checked against the live API when #1037 was written (no key was available), so this needs someone with a Gemini key. Task Move GeminiSmokeSpec to a currently available Gemini model, ideally read from the model registry or a single shared constant instead of a string literal Accept both GOOGLE_API_KEY and GEMINI_API_KEY, as #1037 does Run sbt "it/testOnly *GeminiSmokeSpec" with a real key and confirm it passes Make sure the cloud-smoke job in ci.yml passes whichever key variable the repo secret provides Acceptance criteria Both Gemini smoke suites use the same model and key handling
Context CachedEmbeddingClient and InMemoryEmbeddingCache avoid repeat embedding calls, but the only caching sample is SemanticCachingSample, which covers completions. Task Add EmbeddingCacheExample under modules/samples/src/main/scala/org/llm4s/samples/cache/ that wraps an embedding client in CachedEmbeddingClient, embeds the same text twice, and shows the second call is served from the cache (e.g. by timing or by counting calls through a small wrapper). Use Llm4sConfig for config, not sys.env. Acceptance criteria Runs with sbt "samples/runMain org.llm4s.samples.cache.EmbeddingCacheExample" Output clearly shows cache hit vs miss Getting started See CONTRIBUTING.md. Run sbt scalafmtAll before pushing. Comment here to claim the issue; questions are welcome here or on Discord.
Context modules/samples/.../guardrails/ has samples for input validation, JSON output, composite, custom, factuality and LLM-judge guardrails, but none for PIIMasker. Task Add PIIMaskerExample in that directory that runs a few strings containing emails, phone numbers and similar PII through the guardrail and prints the masked output. Keep it runnable without an API key (call the guardrail directly), and optionally show wiring it into agent.run(... inputGuardrails = ...). Acceptance criteria Runs with sbt "samples/runMain org.llm4s.samples.guardrails.PIIMaskerExample" Mirrors the style of BasicInputValidationExample Getting started See CONTRIBUTING.md. Run sbt scalafmtAll before pushing. Comment here to claim the issue; questions are welcome here or on Discord.
Context The only knowledge-graph sample is Neo4jKnowledgeGraphExample, which requires a running Neo4j. Newcomers can't try the module without extra infrastructure. Task Add InMemoryKnowledgeGraphExample under modules/samples/src/main/scala/org/llm4s/samples/knowledge/ that builds a small graph (nodes and edges) using the in-memory store from modules/knowledgegraph, runs a traversal/query, and prints the results. No LLM or API key should be needed. Use extends App and Result-based error handling per CLAUDE.md. Acceptance criteria Runs with sbt "samples/runMain org.llm4s.samples.knowledge.InMemoryKnowledgeGraphExample" No sys.env or exceptions; follows scalafix rules Getting started See CONTRIBUTING.md. Run sbt scalafmtAll before pushing. Comment here to claim the issue; questions are welcome here or on Discord.
Server side is #1316. Online search says Akka has added these configs but Pekko has no equivalent. Useful for better load balancing in clusters. Connections can be pinned to existing server instances and new instances can be underutilized if we don't encourage clients to seek new connections from time to time. akka.http.client.http2 { persistent-connection-max-age = 10m # 0s = disabled (default) persistent-connection-max-requests = 0 # also available } We should implement a clean room Pekko solution without looking at Akka's impl due to licensing issues.
Summary On a forge whose web UI is cookie-authenticated (GitHub Enterprise, private GitLab), UrlChecker.exists can't tell a repo that exists from one that doesn't β both answer 302 β /login. So every candidate URL is judged absent, and a dependency hosted there gets no Release Notes, no Changelog, no Version Diff, and no repo link, even with a valid <scm><url> in its POM. Proposal: when the URL's host belongs to a configured forge, check existence via that forge's API, while still displaying the web URL. The problem HEAD against a GHE web URL, for a repo that exists and one that doesn't: probe real repo nonexistent repo web, no auth 302 β /login 302 β /login web, Authorization: Basic β¦ (BasicAuthAlg) 302 302 web, Authorization: Bearer β¦ (GitHubAuthAlg) 302 302 API GET /api/v3/repos/org/repo 200 404 Not an auth gap β the web UI ignores Authorization headers and wants a session cookie. In PAT mode BasicAuthAlg.authenticateApi already attaches credentials to
Currently you can get to 400% saturation which sounds scary but if you have parallelism 8 you're actually only half full. So we probably should divide by parallelism.
spark-3.4 is the lowest supported profile, so testWithMinSparkVersion(name, "3.4") is just test(name) with extra indirection. 57 call sites across 14 files, mostly in ScalarFunctionsValidateSuite, DeltaSuite and JsonFunctionsValidateSuite. testWithRangeSparkVersion and ignoreWithSpecifiedSparkVersion in GlutenQueryTest have no callers either. Gates on 3.5 / 4.0 / 4.1 are live and should stay. No behaviour change β the point is that every remaining version gate is then a real one. Best done after #12981. Follow-up to #12807.
eg: this triggers no alert afaik we have such alerts for deployments/stateful sets but I think jobs are not covered by them
Describe the bug make format does not produce code that passes the repo's own scalastyle check, and can itself introduce the violation. make format runs scalafix:scalafix and spotless:apply (scalafmt). scalafmt (scalafmt.conf: maxColumn = 98, rewrite.rules = [Imports]) wraps a long brace-less if/else so that a branch spans multiple lines, but it never inserts braces β scalafmt has no brace-adding rewrite (RedundantBraces only removes them), and none of the configured scalafix rules (ExplicitResultTypes, NoAutoTupling, RemoveUnused, DisableSyntax, LeakingImplicitClassVal, NoValInForComprehension, ProcedureSyntax, RedundantSyntax) add them. scalastyle's IfBraceChecker (dev/scalastyle-config.xml, singleLineAllowed=true, doubleLineAllowed=true) then fails the build with If block needs braces, because a brace-less branch that spans multiple lines is neither single- nor double-line. Since make format does not run scalastyle, it reports success while leaving code that the build/CI rejects,
Describe the bug When --diff / --diff-base is used and the git diff contains no added or modified files β e.g. a change that only deletes files, or no changes at all β scalafix lints (and rewrites) all files instead of none. Root cause JGitDiff drops DELETE entries, so a delete-only diff produces diffs = Nil: https://github.com/scalacenter/scalafix/blob/v0.14.2/scalafix-cli/src/main/scala/scalafix/internal/jgit/JGitDiff.scala#L58 FullDiffDisable.isEmpty is defined as diffs.isEmpty, which makes an empty diff indistinguishable from "no diff requested" (EmptyDiff): https://github.com/scalacenter/scalafix/blob/v0.14.2/scalafix-core/src/main/scala/scalafix/internal/diff/DiffDisable.scala#L29 EscapeHatch.filter short-circuits when isEmpty and returns all patches/diagnostics without any diff-based filtering: https://github.com/scalacenter/scalafix/blob/v0.14.2/scalafix-core/src/main/scala/scalafix/internal/patch/EscapeHatch.scala#L57 https://github.com/scalacenter/scalafix/blob/v0.14.2/s
I have some source files, and a JAR with their compilation results (including META-INF/semanticdb/...). I can, therefore, run a semantic rule: $ scalafix_2.13 --check --scalac-options=-Xsource:3 --rules ExplicitResultTypes --files common/secrets/Secret.scala --classpath bazel-bin/common/secrets/secrets.jar This succeeds. If, however, I add a --classpath with any JAR that does not contain META-INF/semanticdb/... files, I get an error: $ scalafix_2.13 --check --scalac-options=-Xsource:3 --rules ExplicitResultTypes --files common/secrets/Secret.scala --classpath bazel-bin/common/secrets/secrets.jar --classpath ~/.ivy2/cache/junit/junit/jars/junit-4.13.jar error: SemanticDB not found: common/secrets/Secret.scala This is surprising, because the --help says: --classpath Classpath (default: "<classpath>") Full classpath of the files to fix, required for semantic rules. The source files that should be fixed must be compiled with semanticdb-scalac. Dependencies are required by r
Part of #5572. named_struct with duplicate field names falls the whole projection back to Spark: if (expr.names.length != expr.names.distinct.length) { Unsupported(Some(duplicateNamesReason)) } spark/src/main/scala/org/apache/comet/serde/structs.scala:42-43 docs/source/user-guide/latest/expressions.md records it as "Duplicate field names fall back". Spark permits duplicate field names in a struct and CreateNamedStruct.doGenCode builds the row positionally, so the dispatcher reproduces it exactly. StructType is supported by CometBatchKernelCodegen.isSupportedDataType recursively, and duplicate names are not a problem on the Arrow side β the kernel's output field construction is positional too. Worth confirming with a test that the resulting Arrow schema round-trips, since duplicate field names in an Arrow struct are legal but unusual. Fix: mix CodegenDispatchFallback into CometCreateNamedStruct. CometCreateNamedStruct also declines inside convert at :66 when a child fails to seriali
Top Scala Repositories with Beginner Issues (20)
Updated Daily via GitHub GraphQLSplice repository
sbt, the interactive build tool
:robot: A bot that helps you keep your projects up-to-date
β lichess.org: the forever free, adless and open source chess server β
Gluten is a middle layer responsible for offloading JVM-based SQL engines' execution to native engines.
Agentic and LLM Programming in Scala
Code formatter for Scala
Apache DataFusion Comet Spark Accelerator
Refactoring and linting tool for Scala
Toolkit for Scala Development
An open-source storage framework that enables building a Lakehouse architecture with compute engines including Spark, PrestoDB, Flink, Trino, and Hive and APIs
The pure asynchronous runtime for Scala
The Scala Package Index
An OpenTelemetry library for Scala based on Cats-Effect
A minimal, idiomatic Scala interface for HTTP
Simple, Composable, Business-oriented Workflows for Scala
An interactive playground for Scala
Apache Kyuubi is a distributed and multi-tenant gateway to provide serverless SQL on data warehouses and lakehouses.
The first Scala macros' standard library
Expressive types for Spark.
How to make your first Scala open-source pull request
Finding approachable Good First Issues in Scala allows you to build real-world software engineering experience. Instead of submitting PRs to abandoned repositories, GetMerged verifies maintainer review speeds and first-timer acceptance rates before you write a single line of code.
Select any issue above to claim it directly on GitHub, or click a repository to inspect full maintainer review turnaround metrics and triage guidance!
Get this week's top welcoming repos + fresh Good First Issues for Scala
Free weekly email, scoped to Scala. No account needed - confirm once and unsubscribe anytime.