{"record":{"id":"c5825b59c05735d7","repo":"d2lang/d2","slug":"no-available-layout","errorCode":null,"errorMessage":"no available layout","messagePattern":"no available layout","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2lib/d2.go","lineNumber":196,"sourceCode":"\t\t\treturn nil, nil, err\n\t\t}\n\t\td.Scenarios = append(d.Scenarios, ld)\n\t}\n\tprevious := geometry\n\tfor i, l := range g.Steps {\n\t\tld, stepGeometry, err := compileBoard(ctx, l, compileOpts, renderOpts, previous, i+1 < len(g.Steps))\n\t\tif err != nil {\n\t\t\treturn nil, nil, err\n\t\t}\n\t\td.Steps = append(d.Steps, ld)\n\t\tprevious = stepGeometry\n\t}\n\treturn d, geometry, nil\n}\n\nfunc getLayout(opts *CompileOptions) (d2graph.LayoutGraph, error) {\n\tif opts.Layout == nil {\n\t\treturn nil, errors.New(\"no available layout\")\n\t}\n\tif opts.LayoutResolver == nil {\n\t\treturn nil, fmt.Errorf(\"no layout resolver configured for layout engine %q\", *opts.Layout)\n\t}\n\treturn opts.LayoutResolver(*opts.Layout)\n}\n\nfunc getEdgeRouter(opts *CompileOptions) (d2graph.RouteEdges, error) {\n\tif opts.Layout != nil && opts.RouterResolver != nil {\n\t\trouter, err := opts.RouterResolver(*opts.Layout)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif router != nil {\n\t\t\treturn router, nil\n\t\t}\n\t}\n\treturn d2layouts.DefaultRouter, nil","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2lib/d2.go#L178-L214","documentation":"getLayout in d2lib returns this error when CompileOptions.Layout is nil, meaning no layout engine name was supplied for the compilation. Without a layout, the graph cannot be arranged, so compilation aborts.","triggerScenarios":"Calling d2lib.Compile (or compileBoard) with CompileOptions where the Layout *string field is unset and no default layout is applied by the caller.","commonSituations":"Programmatic compilation without setting opts.Layout (e.g. forgetting `d2plugin` default resolution); building CompileOptions by hand in tests/tools; a config path where d2-config layout-engine was not propagated.","solutions":["Set CompileOptions.Layout to a valid engine name, e.g. opts.Layout = &\"dagre\" or \"elk\".","Use the default plugin resolution (dagre) if you want the default behavior — ensure your opts construction includes it.","If relying on d2-config, verify vars.d2-config.layout-engine is set and propagated to CompileOptions.","Check the LayoutResolver is also configured once Layout is set."],"exampleFix":"// before\nopts := &d2lib.CompileOptions{}\ng, err := d2lib.Compile(ctx, ast, opts, nil)\n// after\nlayout := \"dagre\"\nopts := &d2lib.CompileOptions{Layout: &layout}\ng, err := d2lib.Compile(ctx, ast, opts, nil)","handlingStrategy":"fallback","validationCode":"if opts.Layout == nil {\n  l := \"dagre\"\n  opts.Layout = &l\n}","typeGuard":"func layoutConfigured(opts *d2lib.CompileOptions) bool { return opts.Layout != nil }","tryCatchPattern":"g, err := d2lib.Compile(ctx, ast, opts, nil)\nif err != nil && err.Error() == \"no available layout\" {\n  l := \"dagre\"; opts.Layout = &l\n  g, err = d2lib.Compile(ctx, ast, opts, nil)\n}","preventionTips":["Always set CompileOptions.Layout or rely on the CLI/default plugin path that fills it.","Centralize CompileOptions construction so Layout is never forgotten.","Verify vars.d2-config.layout-engine is propagated when using config files."],"tags":["d2","layout","configuration"],"backgroundTag":"missing-layout-engine","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}