Repository navigation
Errors and Edge Cases
UniverseGenerator refuses bad input before it generates anything, with a message that says what to change, and once generation starts it never throws. Settings that are valid but change nothing or read badly are warnings, returned as values. This page lists every refusal the verification run could produce, with its exact message on 1.0.0.
using UniverseGeneration;
void Try(string what, Action action)
{
try
{
action();
Console.WriteLine($"{what}: no error");
}
catch (Exception e)
{
Console.WriteLine($"{what}: {e.GetType().Name}: {e.Message}");
}
}
Try("Systems = 0", () => Galaxy.Generate("my-seed", Preset.Default with { Systems = 0 }));
Try("Systems = 2001", () => Galaxy.Generate("my-seed", Preset.Default with { Systems = 2001 }));
Try("Weirdness = 101", () => Galaxy.Generate("my-seed", Preset.Default with { Weirdness = 101 }));
Try("Arms = 5", () => Galaxy.Generate("my-seed", Preset.Default with { Arms = 5 }));
Try("DangerShift = 6", () => Galaxy.Generate("my-seed", Preset.Default with { DangerShift = 6 }));
Try("a 201-character seed", () => Galaxy.Generate(new string('a', 201)));
Try("an empty seed", () => Galaxy.Generate(""));
Try("a null seed", () => Galaxy.Generate((string)null!));
Try("System(60) of 60", () => Galaxy.Generate("my-seed").System(60));
Try("an unknown level", () => Universe.At("v1-my-seed/galaxy/nebula/0"));
Try("system 60 of 60", () => Universe.At("v1-my-seed/galaxy/system/60"));
Try("generator version 2", () => Universe.At("v2-my-seed/galaxy"));
Try("a link and options", () => Universe.At("v1-my-seed/galaxy?systems=120", Preset.Default));
Try("an unknown option code", () => GeneratorOptions.FromCode("systems=120&colour=red"));
Try("unregistered tables", () => Galaxy.Generate("my-seed", Preset.Default with { Tables = "nobody-registered-this" }));
Try("StarName count 0", () => StarName.Generate("my-seed", 0));
Try("StarName count 1001", () => StarName.Generate("my-seed", 1001));
Try("tables from broken JSON", () => GeneratorTables.FromJson("{"));prints on .NET 10:
Systems = 0: ArgumentException: Systems must be 1 to 2000; you asked for 0. (Parameter 'Systems')
Systems = 2001: ArgumentException: Systems must be 1 to 2000; you asked for 2001. (Parameter 'Systems')
Weirdness = 101: ArgumentException: Weirdness must be 0 to 100; you asked for 101. (Parameter 'Weirdness')
Arms = 5: ArgumentException: Arms must be 2 to 4; you asked for 5. (Parameter 'Arms')
DangerShift = 6: ArgumentException: DangerShift must be -5 to 5; you asked for 6. (Parameter 'DangerShift')
a 201-character seed: ArgumentException: A seed must be at most 200 characters; yours has 201. (Parameter 'seed')
an empty seed: no error
a null seed: ArgumentNullException: A seed is any text, such as "my-seed" or "42"; it cannot be null. (Parameter 'seed')
System(60) of 60: ArgumentOutOfRangeException: This galaxy has 60 systems, numbered 0 to 59; you asked for 60. (Parameter 'index')
Actual value was 60.
an unknown level: ArgumentException: Below v1-my-seed/galaxy comes a system; the address has "nebula". (Parameter 'address')
system 60 of 60: ArgumentException: v1-my-seed/galaxy has 60 systems (numbered 0 to 59); the address asks for system 60. Were the same options passed as when it was generated? (Parameter 'address')
generator version 2: ArgumentException: This package generates version 1; the address asks for version 2. (Parameter 'address')
a link and options: ArgumentException: This link carries its options after the ?; pass a link or options, not both. (Parameter 'address')
an unknown option code: ArgumentException: "colour" is not a setting; the settings are systems, shape, starmix, weirdness, planets, cluster, epoch, arms, lanes, danger, names, require, tables.
unregistered tables: ArgumentException: No tables are registered as "nobody-registered-this"; call GeneratorTables.Register first. (Parameter 'Tables')
StarName count 0: ArgumentException: Count must be 1 to 1000; you asked for 0. (Parameter 'count')
StarName count 1001: ArgumentException: Count must be 1 to 1000; you asked for 1001. (Parameter 'count')
tables from broken JSON: FormatException: Tables JSON, at character 1: expected ".
On .NET Framework 4.8 the messages are the same, but the runtime prints the parameter on a line of its own instead of in brackets, so a message that is shown to users or matched in a test differs between the two:
Systems = 0: ArgumentException: Systems must be 1 to 2000; you asked for 0.
Parameter name: Systems
Match on the exception type and ParamName, not on the whole Message.
-
Catch
ArgumentExceptionaround anything that takes user input: options, seeds, addresses, links and option codes.ArgumentNullExceptionandArgumentOutOfRangeExceptionderive from it.GeneratorTables.FromJsonthrowsFormatExceptionfor JSON it cannot read. -
An empty seed is a seed. Only
nulland seeds over 200 characters (GeneratorOptions.MaxSeedLength) are refused. If an empty text box should not be a world, check for it yourself. - An address that worked can fail with other options. "system 60" of a 60-system galaxy is refused, and the message asks whether the same options were passed: an address does not carry options, a link does (Recipes).
-
A link carries its own options, so
Universe.At(link, options)is refused rather than guessing which to use. -
Tables must be registered first in every program that reads a galaxy made with them, or
GenerateandUniverse.Atrefuse the id.
options.Check() lists settings that are valid but change nothing or read badly, and galaxy.Warnings says what generation had to change. Both are GeneratorWarning values with a WarningCode and a message:
using UniverseGeneration;
var ring = Preset.Default with { Shape = GalaxyShape.Ring, Arms = 3 };
foreach (var w in ring.Check())
Console.WriteLine($"{w.Code}: {w.Message}");
var small = Preset.Default with { Shape = GalaxyShape.Spiral, Systems = 12 };
foreach (var w in small.Check())
Console.WriteLine($"{w.Code}: {w.Message}");
var barren = Preset.Default with { MaxPlanetsPerSystem = 0, Require = Guarantee.GardenWorld };
foreach (var w in Galaxy.Generate("my-seed", barren).Warnings)
Console.WriteLine($"{w.Code}: {w.Message}");prints:
ArmsIgnored: Arms = 3 changes nothing: a ring galaxy has no arms.
ShapeTooSmall: A spiral galaxy of 12 systems: arms read on a map only from 80 systems.
GuaranteeUnmet: Require GardenWorld is not met: no system has a temperate rocky planet to hold it.
The warning codes in 1.0.0 are SystemsTrimmed, ArmsIgnored, ShapeTooSmall, NameNumbered and GuaranteeUnmet (API reference).
-
Systemsfrom 1 to 2,000 (GeneratorOptions.MaxSystems). Systems are built when first read, so a large galaxy costs little until you open it. -
MaxPlanetsPerSystem = 0is accepted; a guarantee that needs a planet then warns, as above. -
Armsis null by default, which lets the generator choose; 2 to 4 are accepted, and they are ignored (with a warning) on shapes without arms. -
Colliding,StarburstandClusteredshapes are made only when you ask for them by name;GalaxyShape.Autonever picks them. -
StarName.Generate(seed, count)takes 1 to 1,000 (StarName.MaxCount). -
Option codes are lowercase
name=valuepairs joined by&, and an unknown name is refused with the list of known ones.
This wiki describes UniverseGenerator 1.0.0 and was last updated on 2026-10-03. The library is MIT licensed. Report problems in the issues. On NuGet: UniverseGenerator. On OpenUPM: com.m4bwav.universe-generator.
Using it
- Getting started
- API reference
- Same seed, same galaxy
- Plausibility rules
- Errors and edge cases
- Recipes
- Feature matrix
- FAQ
The releases
Contributing
Elsewhere