Some uses of incomplete types are ill-formed, such as when you try to declare an object of an incomplete type. However, you can declare a pointer to an incomplete type (for example). In this case that is just what is needed here:
struct node{
struct node *next;
int id;
};