'"Uncaught (in promise) Error: node not found: undefined" when using D3 and JS in browser

I'm new to Node and especially new to D3, and am trying to design a force directed graph. The

forceLink().id 

section throws an error in the browser:

Uncaught (in promise) Error: node not found: undefined
    at find (d3-force.js:124:11)
    at initialize (d3-force.js:157:24)
    at Function.force.initialize (d3-force.js:186:5)
    at initializeForce (d3-force.js:273:13)
    at Object.force (d3-force.js:307:89)
    at drawGraph (app.js:116:10)
    at app.js:220:1

Numerous tutorials and other answers on this site explain my current approach as the correct method, but I may be missing something obvious, such as changes in the API or something else. Can anyone explain why it does not run correctly? Any help would be much appreciated.

Code:

import * as d3 from "https://cdn.skypack.dev/d3@7";

async function drawGraph(){
    var graphData = {
    nodes : [
        { login: 'Bob' },
        { login: 'Carrol' },
        { login: 'John' },
        { login: 'Tanya' },
        { login: 'Sally' },
        { login: 'Louis' }
    ],
    links : [
        { login: 'Bob', parent: 'Carrol', score: '5' },
        { login: 'Carrol', parent: 'John', score: '396' },
        { login: 'John', parent: 'Tanya', score: '387' },
        { login: 'Tanya', parent: 'Tanya', score: '4' },
        { login: 'Tanya', parent: 'John', score: '247' },
        { login: 'John', parent: 'Carrol', score: '86' },
        { login: 'Carrol', parent: 'Tanya', score: '101' },
        { login: 'Carrol', parent: 'Carrol', score: '161' },
        { login: 'John', parent: 'Sally', score: '150' },
        { login: 'Sally', parent: 'Sally', score: '2162' },
        { login: 'Sally', parent: 'Tanya', score: '451' },
        { login: 'John', parent: 'John', score: '1133' },
        { login: 'Bob', parent: 'John', score: '22' },
        { login: 'Tanya', parent: 'Bob', score: '177' },
        { login: 'John', parent: 'Louis', score: '215' },
        { login: 'John', parent: 'Bob', score: '208' },
        { login: 'Louis', parent: 'Bob', score: '15' },
        { login: 'Bob', parent: 'Louis', score: '53' },
        { login: 'Louis', parent: 'Sally', score: '188' }
      ]
};
    const width = window.innerWidth
    const height = window.innerHeight
    const svg = d3.select('svg')
        .attr('width', width)
        .attr('height', height)
    const simulation = d3.forceSimulation(graphData.nodes)
        .force('charge', d3.forceManyBody().strength(-20)) 
        .force('center', d3.forceCenter(width / 2, height / 2))
        .force('link', d3.forceLink(graphData.links).
                    id(function(d){
                            return d.login;})
                        )
        .on("tick", ticked);
        
    // function getNodeColor(node) {
    //     return node.level === 1 ? 'red' : 'gray'
    // }
    const nodeElements = svg.append('g')
            .selectAll('circle')
            .data(graphData.nodes)
            .enter().append('circle')
              .attr('r', 10)
              .attr('fill', function(d){
                  return 'orange';
              })
              .attr("stroke", "yellow");

    const textElements = svg.append('g')
            .selectAll('text')
            .data(graphData.nodes)
            .enter().append('text')
              .text(node => node.login)
              .attr('font-size', 15)
              .attr('dx', 15)
              .attr('dy', 4)
    const linkElements = svg.append('g')
            .selectAll('line')
            .data(graphData.links)
            .enter().append('line')
            .attr('stroke-width', function(d){
                    return 3;
                })
            .attr('stroke', 'pink');
    
    function ticked(){
        nodeElements
                  .attr("cx",  function(d){
                      return d.x;
                  })
                  .attr("cy",  function(d){
                    return d.x;
                  });
        textElements
                  .attr("x", function(d){
                    return d.x;
                })
                  .attr("y", function(d){
                    return d.x;
                });
        linkElements
                  .attr('x1', function(d){
                      return d.parent.x;
                  })
                  .attr('y1', function(d){
                    return d.parent.y;
                  })
                  .attr('x2', function(d){
                    return d.login.x;
                  })
                  .attr('y2', link => function(d){
                    return d.login.y;
                  });
               
    }
    simulation.nodes(graphData.nodes).on('tick', () => {
                nodeElements
                  .attr("cx",  function(d){
                      return d.x;
                  })
                  .attr("cy",  function(d){
                    return d.x;
                });
                textElements
                  .attr("x", function(d){
                    return d.x;
                })
                  .attr("y", function(d){
                    return d.x;
                });
                linkElements
                  .attr('x1', function(d){
                      return d.parent.x;
                  })
                  .attr('y1', function(d){
                    return d.parent.y;
                })
                  .attr('x2', function(d){
                    return d.login.x;
                })
                  .attr('y2', link => function(d){
                    return d.login.y;
                })
               });
}  

drawGraph();

I have tried to change the makeup of the lists (separating them into different list for nodes and links). It also gives an error regardless of it being async or not, and I have tried for forceLink to just use graphData instead of graphData.links as a parameter, which allows the nodes to render but not the links and still throws an error:

Error: <line> attribute y2: Expected length, "function(d){\r\n  …".


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source