diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md
index 0d163a20c..9366912b5 100644
--- a/ci/release/changelogs/next.md
+++ b/ci/release/changelogs/next.md
@@ -4,5 +4,7 @@
#### Bugfixes ⛑️
+- Fixed crash when sequence diagrams had no messages
+ [https://github.com/terrastruct/d2/pull/427](https://github.com/terrastruct/d2/pull/427)
- Fixed serialization affecting binary plugins (TALA).
[https://github.com/terrastruct/d2/pull/426](https://github.com/terrastruct/d2/pull/426)
diff --git a/d2layouts/d2sequence/sequence_diagram.go b/d2layouts/d2sequence/sequence_diagram.go
index 4eeac153a..b05ea10a6 100644
--- a/d2layouts/d2sequence/sequence_diagram.go
+++ b/d2layouts/d2sequence/sequence_diagram.go
@@ -299,14 +299,19 @@ func (sd *sequenceDiagram) placeActors() {
// │
// │
func (sd *sequenceDiagram) addLifelineEdges() {
- lastRoute := sd.messages[len(sd.messages)-1].Route
endY := 0.
- for _, p := range lastRoute {
- endY = math.Max(endY, p.Y)
+ if len(sd.messages) > 0 {
+ lastRoute := sd.messages[len(sd.messages)-1].Route
+ for _, p := range lastRoute {
+ endY = math.Max(endY, p.Y)
+ }
}
for _, note := range sd.notes {
endY = math.Max(endY, note.TopLeft.Y+note.Height)
}
+ for _, actor := range sd.actors {
+ endY = math.Max(endY, actor.TopLeft.Y+actor.Height)
+ }
endY += sd.yStep
for _, actor := range sd.actors {
diff --git a/e2etests/regression_test.go b/e2etests/regression_test.go
index a7eef68c1..7c627be74 100644
--- a/e2etests/regression_test.go
+++ b/e2etests/regression_test.go
@@ -34,6 +34,11 @@ A->B`,
script: `shape: sequence_diagram
b.1 -> b.1
b.1 -> b.1`,
+ }, {
+ name: "sequence_diagram_no_message",
+ script: `shape: sequence_diagram
+a: A
+b: B`,
},
}
diff --git a/e2etests/testdata/regression/sequence_diagram_no_message/dagre/board.exp.json b/e2etests/testdata/regression/sequence_diagram_no_message/dagre/board.exp.json
new file mode 100644
index 000000000..5f1267bc6
--- /dev/null
+++ b/e2etests/testdata/regression/sequence_diagram_no_message/dagre/board.exp.json
@@ -0,0 +1,165 @@
+{
+ "name": "",
+ "shapes": [
+ {
+ "id": "a",
+ "type": "",
+ "pos": {
+ "x": 24,
+ "y": 74
+ },
+ "width": 150,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "A",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 14,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "b",
+ "type": "",
+ "pos": {
+ "x": 274,
+ "y": 74
+ },
+ "width": 150,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "B",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 13,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ }
+ ],
+ "connections": [
+ {
+ "id": "(a -- )[0]",
+ "src": "a",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "a-lifeline-end-2251863791",
+ "dstArrow": "none",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 0,
+ "labelHeight": 0,
+ "labelPosition": "",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 99,
+ "y": 200
+ },
+ {
+ "x": 99,
+ "y": 330
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ },
+ {
+ "id": "(b -- )[0]",
+ "src": "b",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "b-lifeline-end-668380428",
+ "dstArrow": "none",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 0,
+ "labelHeight": 0,
+ "labelPosition": "",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 349,
+ "y": 200
+ },
+ {
+ "x": 349,
+ "y": 330
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ }
+ ]
+}
diff --git a/e2etests/testdata/regression/sequence_diagram_no_message/dagre/sketch.exp.svg b/e2etests/testdata/regression/sequence_diagram_no_message/dagre/sketch.exp.svg
new file mode 100644
index 000000000..04f0e8b4e
--- /dev/null
+++ b/e2etests/testdata/regression/sequence_diagram_no_message/dagre/sketch.exp.svg
@@ -0,0 +1,28 @@
+
+
\ No newline at end of file
diff --git a/e2etests/testdata/regression/sequence_diagram_no_message/elk/board.exp.json b/e2etests/testdata/regression/sequence_diagram_no_message/elk/board.exp.json
new file mode 100644
index 000000000..5f1267bc6
--- /dev/null
+++ b/e2etests/testdata/regression/sequence_diagram_no_message/elk/board.exp.json
@@ -0,0 +1,165 @@
+{
+ "name": "",
+ "shapes": [
+ {
+ "id": "a",
+ "type": "",
+ "pos": {
+ "x": 24,
+ "y": 74
+ },
+ "width": 150,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "A",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 14,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "b",
+ "type": "",
+ "pos": {
+ "x": 274,
+ "y": 74
+ },
+ "width": 150,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "B",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 13,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ }
+ ],
+ "connections": [
+ {
+ "id": "(a -- )[0]",
+ "src": "a",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "a-lifeline-end-2251863791",
+ "dstArrow": "none",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 0,
+ "labelHeight": 0,
+ "labelPosition": "",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 99,
+ "y": 200
+ },
+ {
+ "x": 99,
+ "y": 330
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ },
+ {
+ "id": "(b -- )[0]",
+ "src": "b",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "b-lifeline-end-668380428",
+ "dstArrow": "none",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 0,
+ "labelHeight": 0,
+ "labelPosition": "",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 349,
+ "y": 200
+ },
+ {
+ "x": 349,
+ "y": 330
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ }
+ ]
+}
diff --git a/e2etests/testdata/regression/sequence_diagram_no_message/elk/sketch.exp.svg b/e2etests/testdata/regression/sequence_diagram_no_message/elk/sketch.exp.svg
new file mode 100644
index 000000000..04f0e8b4e
--- /dev/null
+++ b/e2etests/testdata/regression/sequence_diagram_no_message/elk/sketch.exp.svg
@@ -0,0 +1,28 @@
+
+
\ No newline at end of file