When a label has an empty string in it, the result appears to be shifted off by one. Note the bottom right and the bottom left in the second image below.
library(tidyverse)
library(tidygraph)
#>
#> Attaching package: 'tidygraph'
#> The following object is masked from 'package:stats':
#>
#> filter
library(ggraph)
schema <-
create_empty(n=0, directed=TRUE) %>%
bind_nodes(data.frame(id=1:3, label=LETTERS[4:6])) %>%
bind_edges(data.frame(from=c(1, 2, 3), to=c(2, 3, 1), label=c("", LETTERS[1:2])))
ggraph(schema) +
geom_edge_link(aes(label=label)) +
geom_node_label(aes(label=label))
#> Using `nicely` as default layout

ggraph(schema) +
geom_edge_link(aes(label=label), label_parse=TRUE) +
geom_node_label(aes(label=label))
#> Using `nicely` as default layout

Created on 2018-09-14 by the reprex package (v0.2.0).
When a label has an empty string in it, the result appears to be shifted off by one. Note the bottom right and the bottom left in the second image below.
Created on 2018-09-14 by the reprex package (v0.2.0).