Software is bound to fail. Try as we might to create perfect, failure-resistant software, bugs will always exist that might cause software to fail. Notwithstanding this, it is important that this potential failure does not expose an application to a security risk.
An application should feature secure defaults; denying access to resources by default; checking returned values for failure; and making sure that conditional code or filters properly handle failure.
Critically, even though some part of the application is not available, or is functioning unexpectedly, it should not be possible for an attacker to compromise the confidentiality or integrity of an application.
Security before obscurity
Security through obscurity refers to the use of obfuscation or randomization of a design or implementation to provide security. With this in mind, it becomes obvious that the security of a system relying solely on obscurity, rather than the implementation of sound security devices, is destined for failure.
Take for instance, an SSH daemon configured to listen on a port other than the standard port 22. While that may deter a script-kiddie, this obscurity is going to be of little protection against a financially motivated attacker who would not only discover the SSH daemon on the unconventional port, but also notices a series of known and exploitable high-severity vulnerabilities in that daemon.
While obscurity can be used as a defense in depth measure (since it would increase the efforts an attacker needs in order to break into a system), it should never replace real security controls. As such, when obscurity is implemented, it should only be used to increase the cost of attack, and it should always be assumed that a savvy attacker can identify the obscurity and overcome it.
Fail-safe defaults and security before obscurity