Since there's little background here, I thought I'd just add that this feature you're coming across is one of the critical things that underpins Racket and differentiates it from languages like python and ruby. That is, what you're seeing is that Racket has a way to make unforgeable values. This ability is (in addition to lots of stuff, notably macros) is what makes it possible for Racket's class system to be a library and lots of other things that you'd expect to be built into a language to also be libraries.
As a little example, if you have these files:
;; a.rkt
#lang racket
(struct url (stuff more-stuff))
;; b.rkt
#lang racket
(struct url (stuff more-stuff))
;; c.rkt
#lang racket
(require (prefix-in a: "a.rkt") (prefix-in b: "b.rkt"))
(b:url-stuff (a:url 1 2))
you'll see an error message very similar to the one you reported.
It is the struct declaration's location (technically when it is evaluated -- you can even stick them inside functions and each time you call the function you get a different notion of "url") that determines which is which.
This is why, for example, you cannot see the hidden stuff inside the class and object structs. Or, for that matter functions! The "lambda" that #lang racket exports is a lot fancier than the low-level built-in lambda, and that is all implemented with structs. Indeed, you cannot tell what is primitive and what is implemented with a struct in some private file (unless you read the source code). Or, to put it another way: everything is implemented with struct and the runtime system is just good at optimizing a small subset of the structs where performance matters.
Robby