Very commonly, this has to do with how the service was initialized.
The service configuration allows you to specify what access you want clients to have (by default) on entity sets. You may further restrict access through interceptors, but you can never grant more access than that specified on the configuration.
One of the interesting things that the service will do is to hide entity sets for which clients have no access rights at all. This includes hiding the entity set itself from the URL space (so requests trying to get to it receive a 404 Resource Not Found response), hiding navigation properties that refer to that entity set, and hiding the entity set (and “orphaned” types) from the CSDL produced by $metadata.
This behavior enables you to have entity sets in your model that you can use reference from query interceptors and the like (for example if you have a “rights” table you want to use to further restrict access), but that aren’t really part of the service you want to expose. Nifty, right?
By default, the service is completely locked down – all the entity sets have no access rights granted for them, and so the data service looks empty – you can’t access any resource at all. That’s why folks are sometimes baffled when “everything works”, but nothing is accessible. You should implement the InitializeService method and start granting access on a per-entity-set basis, and then you’re ready to go.